@stacksjs/ts-cloud 0.12.12 → 0.12.13
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.
- package/dist/aws/index.js +1 -1
- package/dist/bin/chunk-0vsxpmfj.js +3 -0
- package/dist/bin/chunk-12e9v1dw.js +3 -0
- package/dist/bin/chunk-13dhcjjb.js +60 -0
- package/dist/bin/chunk-1fj5gk6r.js +725 -0
- package/dist/bin/chunk-1j2sja1j.js +1 -0
- package/dist/bin/chunk-1s4dny8d.js +1 -0
- package/dist/bin/chunk-2hpnd4g4.js +1 -0
- package/dist/bin/chunk-49sthm4q.js +2 -0
- package/dist/bin/chunk-4yntpqbe.js +1 -0
- package/dist/bin/chunk-4zbnwt9b.js +2 -0
- package/dist/bin/chunk-55kmbzr5.js +1 -0
- package/dist/{chunk-2ybcnrte.js → bin/chunk-57w9nsjk.js} +3 -3
- package/dist/bin/chunk-5gehfky4.js +2 -0
- package/dist/bin/chunk-6xw0r4gn.js +7364 -0
- package/dist/bin/chunk-6zk2n3wk.js +511 -0
- package/dist/bin/{chunk-wcem4cqb.js → chunk-7a7n6p2m.js} +2 -2
- package/dist/bin/chunk-7h6h8yxm.js +6 -0
- package/dist/bin/chunk-7x0hrna6.js +1 -0
- package/dist/bin/{chunk-e2dnxp8d.js → chunk-80zkjpfz.js} +29 -29
- package/dist/bin/chunk-84tvv3x1.js +1 -0
- package/dist/bin/chunk-94cfdvrn.js +2 -0
- package/dist/bin/chunk-96xtj5j6.js +1 -0
- package/dist/bin/chunk-9jfjzycs.js +111 -0
- package/dist/{chunk-ac87ds1k.js → bin/chunk-bckm6fre.js} +6 -6
- package/dist/bin/chunk-bnv8yd9w.js +6 -0
- package/dist/bin/chunk-c51xp8f7.js +1 -0
- package/dist/bin/chunk-d5qhwtkg.js +9 -0
- package/dist/bin/chunk-d7r6mhyv.js +34 -0
- package/dist/bin/chunk-de88yqwy.js +1 -0
- package/dist/bin/chunk-dh2qmxw9.js +1 -0
- package/dist/bin/chunk-dhxwmkhz.js +2 -0
- package/dist/bin/chunk-f35pte64.js +44 -0
- package/dist/bin/{chunk-jxd3j00s.js → chunk-gj5jkhfr.js} +13 -13
- package/dist/bin/chunk-jcyrm5q0.js +2 -0
- package/dist/bin/chunk-jh1593zx.js +1 -0
- package/dist/bin/chunk-nnkhrm4n.js +8 -0
- package/dist/bin/chunk-p36ns96s.js +1 -0
- package/dist/bin/{chunk-t5ngva49.js → chunk-p9hd27k4.js} +8 -8
- package/dist/bin/chunk-qz3za76g.js +1 -0
- package/dist/bin/chunk-r6cvc2pr.js +1 -0
- package/dist/bin/chunk-rh2sqtew.js +1 -0
- package/dist/bin/chunk-rxwecjgc.js +1 -0
- package/dist/bin/chunk-tkzpbb7n.js +1 -0
- package/dist/bin/chunk-vx649y7t.js +1 -0
- package/dist/bin/chunk-vymg9ywg.js +2 -0
- package/dist/bin/chunk-w7k5rvmw.js +1 -0
- package/dist/bin/chunk-wge61ccr.js +2 -0
- package/dist/bin/chunk-wvhqjr80.js +2 -0
- package/dist/bin/chunk-x5x9dzk7.js +3 -0
- package/dist/bin/chunk-xaafj6kf.js +1 -0
- package/dist/bin/chunk-xgepx8yx.js +1 -0
- package/dist/bin/{chunk-t7rcfwqc.js → chunk-yhxpmk29.js} +32 -32
- package/dist/bin/chunk-ymbwekjm.js +1 -0
- package/dist/bin/chunk-yn34zgr2.js +1 -0
- package/dist/bin/chunk-ynr22ma8.js +2 -0
- package/dist/bin/chunk-yt8rgkqt.js +2 -0
- package/dist/bin/chunk-z2ez8wn9.js +37 -0
- package/dist/bin/cli.js +428 -428
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/chunk-13d54txj.js +44 -0
- package/dist/chunk-1kp3y2s7.js +1 -0
- package/dist/chunk-1n3ckctd.js +7355 -0
- package/dist/chunk-30h9rgfn.js +6 -0
- package/dist/chunk-3kapcdpn.js +92 -0
- package/dist/chunk-3qp10j0j.js +5 -0
- package/dist/chunk-6g81m01r.js +141 -0
- package/dist/{chunk-6cxb8d6y.js → chunk-6nvn041c.js} +3 -3
- package/dist/chunk-7by4rm7y.js +1 -0
- package/dist/chunk-7ww65b66.js +709 -0
- package/dist/chunk-9c29rnk3.js +22 -0
- package/dist/chunk-9w32efae.js +1 -0
- package/dist/chunk-e0919h5g.js +2 -0
- package/dist/{chunk-dndxwssj.js → chunk-e7ds04wb.js} +2 -2
- package/dist/chunk-edqhhcg9.js +4 -0
- package/dist/chunk-ej4sm2tw.js +60 -0
- package/dist/chunk-emg3shmb.js +2 -0
- package/dist/chunk-fdexq9e1.js +1 -0
- package/dist/chunk-g8fpsdyq.js +37 -0
- package/dist/chunk-jb8em9ba.js +2 -0
- package/dist/chunk-n688m5fp.js +1 -0
- package/dist/chunk-r5emv4x8.js +2 -0
- package/dist/{chunk-q9a1z53k.js → chunk-sct6mdgc.js} +51 -51
- package/dist/chunk-thpce63q.js +34 -0
- package/dist/chunk-tnjae324.js +585 -0
- package/dist/{bin/chunk-m9r5jype.js → chunk-wjgnfg6q.js} +6 -6
- package/dist/chunk-wpqj98h8.js +2 -0
- package/dist/chunk-wrnhbb13.js +1 -0
- package/dist/chunk-zftpjxkr.js +2 -0
- package/dist/chunk-zmyv76f0.js +114 -0
- package/dist/deploy/index.js +1 -1
- package/dist/dns/index.js +1 -1
- package/dist/drivers/index.d.ts +1 -0
- package/dist/drivers/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +91 -91
- package/dist/operations/index.js +1 -1
- package/dist/protection/index.js +1 -1
- package/dist/push/index.js +1 -1
- package/dist/spend/index.js +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/accept-invitation.html +1 -1
- package/dist/ui/access-denied.html +1 -1
- package/dist/ui/account/automation.html +5 -5
- package/dist/ui/account/security.html +1 -1
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +1 -1
- package/dist/ui/data/backups.html +6 -6
- package/dist/ui/data/services.html +7 -7
- package/dist/ui/data/volumes.html +5 -5
- package/dist/ui/index.html +6 -6
- package/dist/ui/infrastructure/topology.html +9 -9
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +6 -6
- package/dist/ui/operations/configuration.html +5 -5
- package/dist/ui/operations/jobs.html +6 -6
- package/dist/ui/operations/maintenance.html +5 -5
- package/dist/ui/operations/observability.html +6 -6
- package/dist/ui/operations/previews.html +6 -6
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +5 -5
- package/dist/ui/operations/releases.html +6 -6
- package/dist/ui/operations/spend.html +6 -6
- package/dist/ui/operations/workloads.html +10 -10
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +6 -6
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +6 -6
- package/dist/ui/server/deployments.html +5 -5
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +6 -6
- package/dist/ui/server/fleet.html +6 -6
- package/dist/ui/server/logs.html +5 -5
- package/dist/ui/server/metrics.html +5 -5
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +17 -17
- package/dist/ui/server/ssh-keys.html +5 -5
- package/dist/ui/server/team.html +5 -5
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +6 -6
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +6 -6
- package/dist/ui/serverless/deployments.html +2 -2
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +6 -6
- package/dist/ui/serverless/logs.html +6 -6
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +6 -6
- package/dist/ui/serverless/secrets.html +6 -6
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +6 -6
- package/dist/ui-src/src/charts.ts +1141 -1294
- package/dist/ui-src/src/topology.ts +3 -3
- package/package.json +3 -3
- package/dist/bin/chunk-0b49jjgr.js +0 -2
- package/dist/bin/chunk-0xnnkeb1.js +0 -1
- package/dist/bin/chunk-227jmf2b.js +0 -2
- package/dist/bin/chunk-2nyyg44g.js +0 -1
- package/dist/bin/chunk-2ztr119n.js +0 -3
- package/dist/bin/chunk-43xj5cny.js +0 -1
- package/dist/bin/chunk-5w6y9pmz.js +0 -1
- package/dist/bin/chunk-5x4rdx8k.js +0 -37
- package/dist/bin/chunk-6zc6a6t3.js +0 -725
- package/dist/bin/chunk-7aagqqr9.js +0 -1
- package/dist/bin/chunk-85qrgshq.js +0 -44
- package/dist/bin/chunk-8zk8msx0.js +0 -2
- package/dist/bin/chunk-9j83q0r4.js +0 -1
- package/dist/bin/chunk-9nhqbes6.js +0 -60
- package/dist/bin/chunk-a4js49mx.js +0 -1
- package/dist/bin/chunk-a9e0hvwe.js +0 -6
- package/dist/bin/chunk-a9tgxf2h.js +0 -1
- package/dist/bin/chunk-aahrv359.js +0 -1
- package/dist/bin/chunk-bfx23be3.js +0 -1
- package/dist/bin/chunk-bpps61am.js +0 -111
- package/dist/bin/chunk-bzth6d1s.js +0 -6
- package/dist/bin/chunk-ca3taw2m.js +0 -1
- package/dist/bin/chunk-cgzp0328.js +0 -1
- package/dist/bin/chunk-d2aaef9v.js +0 -1
- package/dist/bin/chunk-e0z2t4mf.js +0 -6
- package/dist/bin/chunk-empfsmdk.js +0 -2
- package/dist/bin/chunk-er3mww4m.js +0 -1
- package/dist/bin/chunk-fmp5bv0j.js +0 -3
- package/dist/bin/chunk-g3kp5ddx.js +0 -1
- package/dist/bin/chunk-grepda40.js +0 -1
- package/dist/bin/chunk-h6xqtypj.js +0 -2
- package/dist/bin/chunk-hwk9ahms.js +0 -2
- package/dist/bin/chunk-k1xw3zbm.js +0 -34
- package/dist/bin/chunk-m07s5esk.js +0 -2
- package/dist/bin/chunk-n20kbxwb.js +0 -7364
- package/dist/bin/chunk-n2fnav53.js +0 -3
- package/dist/bin/chunk-nv211m42.js +0 -8
- package/dist/bin/chunk-psgjy3z4.js +0 -1
- package/dist/bin/chunk-qmnr82da.js +0 -1
- package/dist/bin/chunk-qqpb82ty.js +0 -2
- package/dist/bin/chunk-rqc8btkj.js +0 -2
- package/dist/bin/chunk-rs85xvt7.js +0 -1
- package/dist/bin/chunk-sj5csg49.js +0 -2
- package/dist/bin/chunk-tjgy10zm.js +0 -9
- package/dist/bin/chunk-v0beqdna.js +0 -1
- package/dist/bin/chunk-vf2s3tba.js +0 -1
- package/dist/bin/chunk-vzkfjrx2.js +0 -511
- package/dist/bin/chunk-wsh5ervz.js +0 -1
- package/dist/bin/chunk-xenhbdmr.js +0 -1
- package/dist/bin/chunk-xrdpxwbf.js +0 -1
- package/dist/bin/chunk-y68m9bx7.js +0 -2
- package/dist/chunk-4884der5.js +0 -1
- package/dist/chunk-4wdxsnn2.js +0 -44
- package/dist/chunk-5hhyyhjt.js +0 -1
- package/dist/chunk-5zkacdw1.js +0 -1
- package/dist/chunk-6f68caq0.js +0 -1
- package/dist/chunk-7z50g5xz.js +0 -4
- package/dist/chunk-8fh4m5ge.js +0 -1
- package/dist/chunk-97pb7wb1.js +0 -1
- package/dist/chunk-ea7tn8nn.js +0 -709
- package/dist/chunk-ess6vxfj.js +0 -2
- package/dist/chunk-j06r5rwv.js +0 -2
- package/dist/chunk-j1g67djb.js +0 -92
- package/dist/chunk-k8x8mrkr.js +0 -2
- package/dist/chunk-mnmz8t7q.js +0 -34
- package/dist/chunk-n1fyryha.js +0 -141
- package/dist/chunk-n1hg0jxs.js +0 -2
- package/dist/chunk-n5xmh0ma.js +0 -37
- package/dist/chunk-q22qfwsc.js +0 -22
- package/dist/chunk-r8t25tbm.js +0 -7355
- package/dist/chunk-t8hzekmk.js +0 -585
- package/dist/chunk-whyttetx.js +0 -5
- package/dist/chunk-yf8stygs.js +0 -114
- package/dist/chunk-ze5x2bpm.js +0 -2
- package/dist/chunk-zh0apedk.js +0 -60
- package/dist/chunk-zjyz926j.js +0 -2
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import{Ds,Ke,A,V,C,U,Pe,jt}from"./chunk-6xw0r4gn.js";import{ie,Yr,Z,Zr,h,Tr,Cs}from"./chunk-gj5jkhfr.js";import{_e,b,$o,er,jn,Vn,nt,Lr,la,Nt,Mr,Be,$e,Fe,da,ot,tr,Oe,je,zn,qn,Ai,Ii,Ve,Ur,ir,st,p,$i,Ko,Jo}from"./chunk-9jfjzycs.js";import{u}from"./chunk-bckm6fre.js";import{le}from"./chunk-49sthm4q.js";import{f}from"./chunk-80zkjpfz.js";import{hr,St,yr,Sr,br,vr,Qr}from"./chunk-nnkhrm4n.js";import{qe,cr,Ji,x,Wr,_a,$a,$t,ei,ti}from"./chunk-1fj5gk6r.js";import{v}from"./chunk-vymg9ywg.js";import{ne,X,Xn}from"./chunk-0vsxpmfj.js";import{w}from"./chunk-yhxpmk29.js";import{F}from"./chunk-dhxwmkhz.js";import{R}from"./chunk-4zbnwt9b.js";import{W,P,M,gr,co,fr,Gr}from"./chunk-d5qhwtkg.js";import{no}from"./chunk-bnv8yd9w.js";import{H,Zo,es,zi,_t,j,ts}from"./chunk-x5x9dzk7.js";import{Xo,Qo}from"./chunk-12e9v1dw.js";import{_o}from"./chunk-94cfdvrn.js";import{Xr}from"./chunk-5gehfky4.js";import{createHash as xT}from"node:crypto";import{existsSync as lo,mkdtempSync as ip,readdirSync as eb,rmSync as Ss,statSync as lb}from"node:fs";import{readFile as Fi,writeFile as ys}from"node:fs/promises";import{tmpdir as Cd}from"node:os";import{dirname as DT,extname as za,join as Et,normalize as OT,relative as _T,resolve as NT,sep as $T}from"node:path";import{fileURLToPath as MT}from"node:url";class Od extends Error{status;code;requestId;constructor(e,t,r,n){super(r);this.status=e;this.code=t;this.requestId=n}}class Ci{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 Od(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 yS}from"node:crypto";import{lstatSync as Ab,readdirSync as kb,readFileSync as Rb}from"node:fs";import{relative as Pb,resolve as Ap,sep as xb}from"node:path";function Db(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 kp(e){try{return e?.content?JSON.parse(e.content):{}}catch{return{}}}function As(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 At(e){let t=Db(e.slice(0,1e4)),r=[];if(t.has("Dockerfile"))r.push(As("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=kp(t.get("composer.json"));if(t.has("artisan")&&n.require?.["laravel/framework"])r.push(As("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(As("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=kp(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,m=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(As(c,m.kind,Math.min(0.94,l.reduce((E,k)=>E+k.weight,0)),l,m,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(As("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(As("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 Pn(e,t={}){let r=Ap(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 m of kb(a).sort()){if(c.has(m))continue;let E=Ap(a,m),k=Pb(r,E).split(xb).join("/");if(!k||k.startsWith("../"))throw Error("Detection path escaped the application root");let O=Ab(E);if(O.isSymbolicLink())throw Error(`Detection refuses symbolic links: ${k}`);if(O.isDirectory())l(E);else if(O.isFile()){if(o.length>=n)throw Error("Application file-count limit exceeded");let q={path:k,size:O.size};if(s.has(k)&&O.size<=i)q.content=Rb(E,"utf8");o.push(q)}}};return l(r),o}function Nd(e){if(Array.isArray(e))return`[${e.map(Nd).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)}:${Nd(r)}`).join(",")}}`;return JSON.stringify(e)??"null"}function ga(e){return!!e&&!e.startsWith("/")&&!e.split("/").includes("..")&&!/[\0\r\n]/.test(e)}function Hn(e,t,r,n){return{path:e,code:t,message:r,alternatives:n}}function _d(e){return JSON.parse(JSON.stringify(e))}function Ob(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 _d({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 _d({serverless:{apps:{[e.slug]:{source:e.source,build:e.build,architecture:e.runtime.architecture,environment:t,domain:e.domain}}}});return _d({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 se(e,t=[]){let r=[],n=(q)=>/(?:secret|token|password|passwd|private[_-]?key|api[_-]?key)/i.test(q),i=Object.fromEntries(Object.entries(e.environment??{}).map(([q,G])=>{if(typeof G==="string"&&n(q))return r.push(Hn(`environment.${q}`,"write_only_secret_required",`${q} must be supplied through the write-only secrets boundary.`)),[q,{secretRef:q}];return[q,G]})),o=e.build;if(e.build.kind==="dockerfile"&&e.build.buildArgs){let q=Object.fromEntries(Object.entries(e.build.buildArgs).map(([G,Y])=>{if(n(G))return r.push(Hn(`build.buildArgs.${G}`,"write_only_build_secret_required",`${G} must be declared in secretNames instead of buildArgs.`)),[G,"[REDACTED]"];return[G,Y]}));o={...e.build,buildArgs:q}}if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.slug))r.push(Hn("slug","invalid_slug","Slug must contain 2-63 lowercase letters, numbers, or hyphens."));if(!ga((e.source.kind==="git"?e.source.monorepoRoot:e.source.kind==="local"?e.source.root:".")??"."))r.push(Hn("source","unsafe_source_root","Source root must stay inside the source tree."));if(e.source.kind==="git"&&e.source.sparsePaths?.some((q)=>!ga(q)))r.push(Hn("source.sparsePaths","unsafe_sparse_path","Sparse checkout paths must stay inside the repository."));if(e.build.kind==="dockerfile"&&(!ga(e.build.context)||!ga(e.build.dockerfile)))r.push(Hn("build","unsafe_docker_path","Docker context and Dockerfile must stay inside the source tree."));if(e.build.kind==="static"&&!ga(e.build.publishDirectory))r.push(Hn("build.publishDirectory","invalid_publish_directory","A safe static publish directory is required."));if(e.build.kind==="server"&&!e.build.startCommand.trim())r.push(Hn("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(Hn("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(Hn("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(Hn("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(Hn("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(Hn("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(Hn("domain.hostname","invalid_domain","Domain must be a valid DNS hostname."));let c=Object.values(i).flatMap((q)=>typeof q==="object"?[q.secretRef]:[]),l=[...new Set([...e.requiredSecretNames??[],...e.build.kind==="dockerfile"?e.build.secretNames??[]:[],...c])].sort(),a=new Set(t),m=l.filter((q)=>!a.has(q)),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}},k=[...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(),O=[...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&&m.length===0,issues:r,missingSecrets:m,manifest:E,configPatch:Ob({...e,build:o,environment:i}),capabilityRequirements:k,costDrivers:O,serializedManifest:`${Nd(E)}
|
|
2
|
+
`}}function Rp(e){let t=e.replace(/\\/g,"/");return!!t&&!t.startsWith("/")&&!/^[A-Za-z]:\//.test(t)&&!t.split("/").includes("..")&&!/[\0\r\n]/.test(t)}function Pp(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 m=0;while(m+30<=e.length){let E=s.getUint32(m,!0);if(E===33639248||E===101010256)break;if(E!==67324752)throw Error("Malformed ZIP local header");let k=s.getUint16(m+6,!0),O=s.getUint32(m+18,!0),q=s.getUint32(m+22,!0),G=s.getUint16(m+26,!0),Y=s.getUint16(m+28,!0);if(k&8)throw Error("ZIP data descriptors are not accepted for uploaded artifacts");let re=new TextDecoder().decode(e.subarray(m+30,m+30+G));if(!Rp(re))throw Error(`Unsafe archive path: ${re}`);if(c.push(re),l+=q,c.length>i||l>o)throw Error("Archive expansion limit exceeded");m+=30+G+Y+O}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 m=e.subarray(a,a+512);if(m.every((G)=>G===0))break;let E=(G,Y)=>new TextDecoder().decode(m.subarray(G,G+Y)).replace(/\0.*$/,""),k=`${E(345,155)}${E(345,155)?"/":""}${E(0,100)}`,O=Number.parseInt(E(124,12).trim()||"0",8),q=String.fromCharCode(m[156]??0);if(!Rp(k))throw Error(`Unsafe archive path: ${k}`);if(q==="1"||q==="2")throw Error(`Archive links are not accepted: ${k}`);if(!Number.isFinite(O)||O<0)throw Error("Malformed TAR entry size");if(c.push(k),l+=O,c.length>i||l>o)throw Error("Archive expansion limit exceeded");a+=512+Math.ceil(O/512)*512}return{format:"tar",entries:c.length,expandedBytes:l,paths:c}}var xp=new Set(["source","build","runtime","environment","domain","review"]);function Dp(e,t){try{return typeof e==="string"?JSON.parse(e):t}catch{return t}}function Op(e){return/(?:secret|token|password|passwd|private[_-]?key|api[_-]?key)/i.test(e)}function _p(e){for(let[r,n]of Object.entries(e.environment??{}))if(typeof n==="string"&&Op(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(Op(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 Np(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:Dp(e.input,{}),suppliedSecretNames:Dp(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 Nn{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(_p(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(!xp.has(i))throw Error("Invalid draft step");let o=[...new Set(e.suppliedSecretNames??[])].sort(),s=se(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?Np(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(Np)}update(e,t,r){let n=this.get(e);if(!n||n.version!==t)throw Error(`Application draft ${e} changed since version ${t}`);if(!xp.has(r.step))throw Error("Invalid draft step");if(r.draft.projectId!==n.projectId)throw Error("Draft project cannot be changed");_p(r.draft);let i=[...new Set(r.suppliedSecretNames??n.suppliedSecretNames)].sort(),o=se(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=se(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 _b,createDecipheriv as Nb,createHash as Lp,randomBytes as $b}from"node:crypto";function ma(e){return typeof e==="string"&&e?e:void 0}function $d(e){return Lp("sha256").update(e).digest("hex").slice(0,16)}function $p(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 Mb(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:ma(e.credential_fingerprint),credentialExpiresAt:ma(e.credential_expires_at),status:String(e.status),healthMessage:ma(e.health_message),lastTestedAt:ma(e.last_tested_at),version:Number(e.version),createdByActorId:ma(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class kn{controlPlane;key;nowFn;idFn;constructor(e,t){this.controlPlane=e;if(!t.encryptionKey)throw Error("Registry encryption key is required");this.key=Lp("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=$b(12),r=_b("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=Nb("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=Mb(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),$p(e.host),t?this.encrypt(t):null,t?$d(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:$p(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),$d(i),r.expiresAt??null,this.now(),e]),this.controlPlane.appendEvent({organizationId:n.organizationId,actorId:r.actorId,type:"registry.credential.rotated",payload:{connectionId:e,fingerprint:$d(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 k=Object.fromEntries([...a.slice(7).matchAll(/(\w+)="([^"]+)"/g)].map((re)=>[re[1],re[2]])),O=new URL(k.realm??"");if(O.protocol!=="https:")throw Error("Registry authentication realm must use HTTPS");if(k.service)O.searchParams.set("service",k.service);if(t.image)O.searchParams.set("scope",`repository:${Bp(t.image).repository}:pull`);let q=await i(O,{signal:o.signal,redirect:"error",headers:c?{Authorization:c}:void 0});if(!q.ok)throw Error(`Registry authentication failed (${q.status})`);let G=await q.json(),Y=G.token??G.access_token;if(!Y)throw Error("Registry did not return an access token");l=t.image?await Mp(i,r.host,t.image,Y,o.signal):await i(`${r.host}/v2/`,{signal:o.signal,redirect:"error",headers:{Authorization:`Bearer ${Y}`}})}else if(l.ok&&t.image)l=await Mp(i,r.host,t.image,n?.token,o.signal,c);let m=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=?",[m,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 Bp(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 Mp(e,t,r,n,i,o){let s=Bp(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 Lb}from"node:crypto";import{chmodSync as jp,existsSync as Fp,mkdirSync as Bb,renameSync as jb,unlinkSync as Up,writeFileSync as Fb}from"node:fs";import{basename as Ub,join as zb}from"node:path";function Md(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 Dn{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=Ub(e.filename).slice(0,200);if(!r||r!==e.filename)throw Error("Artifact filename must not contain a path");let n=Pp(e.bytes,r),i=Lb("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 Md(o);let s=this.idFn();Bb(this.root,{recursive:!0,mode:448}),jp(this.root,448);let c=zb(this.root,`${s}.archive`),l=`${c}.partial`;try{Fb(l,e.bytes,{mode:384,flag:"wx"}),jb(l,c),jp(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(Fp(l))Up(l);if(Fp(c))Up(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?Md(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(Md)}}function Nr(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=se(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 Qt(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 Qa(e,t){let r=Qt(e).find((n)=>n.strategy===t);if(!r.supported)throw Error(`${t} is unavailable: ${r.explanation}`);return r}import{createHash as Vb}from"node:crypto";var qb=/^sha256:[a-f0-9]{64}$/,Jb=/^[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 zp(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 Vp(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 Wb(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 Hb(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 Ld{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}registerArtifact(e){if(!qb.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 zp(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?zp(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&&!Jb.test(e.sourceSha))throw Error("Release source must be an immutable commit SHA");Qa({kind:e.kind,provider:r.provider,hasHealthGate:!!e.healthGate,replicas:e.replicas},e.strategy);let i=h(e.config),o=Vb("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",m=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(m),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?Vp(t):void 0}list(e={}){return this.controlPlane.database.query("SELECT * FROM releases ORDER BY created_at DESC, rowid DESC").all().map(Vp).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(Wb)}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:Hb(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 et{controlPlane;releases;queue;constructor(e){this.controlPlane=e;this.releases=new Ld(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 Gb(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 qp(e,t){if(t.release.artifactId!==t.artifact.id)throw Error("Release activation artifact identity changed");Qa({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:Gb(t.release)})}async function Jp(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 Kb=["release.activate","release.rollback"];function Qb(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function Wp(e){let t=new et(e.store),r=async(n)=>{let i=Qb(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 m=await e.resolveDriver(s);n.checkpoint("verify",`Verifying ${c.digest} and ${s.configHash} for ${m.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 Jp(m,{release:s,artifact:c,previous:a}):await qp(m,{release:s,artifact:c,previous:a})}catch(k){if(n.operation.kind==="release.activate"&&t.releases.get(s.id)?.status==="activating")t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,message:k instanceof Error?k.message:String(k)});throw k}for(let k of E.transitions)t.releases.progress(s.id,{message:`${n.operation.kind==="release.rollback"?"Rollback":"Activation"} traffic at ${k.trafficPercent}%.`,trafficPercent:k.trafficPercent,health:k.observed,operationId:n.operation.id}),n.log(`Traffic ${k.trafficPercent}%: ${k.healthy?"healthy":"unhealthy"}.`,{stream:k.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??`${m.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 k=await e.resolveHealthGate(s.healthGate.name,s);if(n.log(`${s.healthGate.name}: ${k.healthy?"healthy":"unhealthy"}${k.message?` — ${k.message}`:""}.`,{stream:k.healthy?"step":"stderr",step:"health"}),!k.healthy)throw t.completeHealthGate(s.id,{healthy:!1,operationId:n.operation.id,health:k.evidence,message:k.message??`Named health gate ${s.healthGate.name} failed.`}),Error(k.message??`Named health gate ${s.healthGate.name} failed`)}if(n.operation.kind==="release.rollback"){let k=t.releases.get(s.id);if(k.status!=="rolled_back")t.releases.transition(k.id,"rolled_back",{message:`Traffic restored through ${m.name}.`,operationId:n.operation.id,trafficPercent:0,health:{resourceVersions:E.resourceVersions}});if(a&&a.status!=="active"){let O=a.status==="activating"?a:t.releases.transition(a.id,"activating",{message:"Rollback target restoring traffic.",operationId:n.operation.id,trafficPercent:0});t.releases.transition(O.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:m.name,providerVersion:E.providerVersion??null,resourceVersions:E.resourceVersions,status:t.releases.get(s.id).status}};return Object.fromEntries(Kb.map((n)=>[n,r]))}import{createCipheriv as Yb,createDecipheriv as Xb,createHash as Yp,randomBytes as Bd}from"node:crypto";var Xp={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 Pt(e){return typeof e==="string"&&e?e:void 0}function Ho(e,t){try{return typeof e==="string"?JSON.parse(e):t}catch{return t}}function Ni(e){return JSON.stringify(h(e))}function Wo(e){return Yp("sha256").update(e).digest("hex")}function Hp(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 Gp(e){let t=e.trim();if(t.length<2||t.length>80)throw Error("Connection name must contain 2-80 characters");return t}function jd(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 Kp(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 Ya(e){return[...new Set((e??[]).map((t)=>t.trim()).filter(Boolean))].slice(0,100)}function Zb(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 eS(e){return{id:String(e.id),organizationId:String(e.organization_id),provider:String(e.provider),name:String(e.name),host:String(e.host),owner:Pt(e.owner),authKind:String(e.auth_kind),credentialConfigured:!!e.credential_ciphertext,credentialFingerprint:Pt(e.credential_fingerprint),grantedScopes:Ho(e.granted_scopes,[]),capabilities:Ho(e.capabilities,Xp[String(e.provider)]),status:String(e.status),healthMessage:Pt(e.health_message),lastTestedAt:Pt(e.last_tested_at),lastSyncedAt:Pt(e.last_synced_at),credentialExpiresAt:Pt(e.credential_expires_at),version:Number(e.version),createdByActorId:Pt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Fd(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:Ho(e.metadata,{}),syncedAt:String(e.synced_at)}}function Qp(e){return{id:String(e.id),projectId:String(e.project_id),environmentId:Pt(e.environment_id),resourceId:Pt(e.resource_id),connectionId:String(e.connection_id),repositoryId:Pt(e.repository_id),repositoryFullName:String(e.repository_full_name),defaultBranch:String(e.default_branch),branchRule:Pt(e.branch_rule),tagRule:Pt(e.tag_rule),monorepoRoot:String(e.monorepo_root),includePaths:Ho(e.include_paths,[]),excludePaths:Ho(e.exclude_paths,[]),submodules:Number(e.submodules)===1,cloneDepth:e.clone_depth==null?void 0:Number(e.clone_depth),deployKeyId:Pt(e.deploy_key_id),autoDeploy:Number(e.auto_deploy)===1,pullRequestPreviews:Number(e.pull_request_previews)===1,status:String(e.status),disabledReason:Pt(e.disabled_reason),version:Number(e.version),createdByActorId:Pt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ud(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:Pt(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function zd(e){return{id:String(e.id),connectionId:String(e.connection_id),repositoryId:Pt(e.repository_id),repositoryFullName:String(e.repository_full_name),providerWebhookId:Pt(e.provider_webhook_id),events:Ho(e.events,[]),status:String(e.status),healthMessage:Pt(e.health_message),lastDeliveryAt:Pt(e.last_delivery_at),lastReconciledAt:Pt(e.last_reconciled_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Vd(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:Pt(e.action),commitSha:Pt(e.commit_sha),signatureStatus:String(e.signature_status),status:String(e.status),payloadSummary:Ho(e.payload_summary,{}),operationId:Pt(e.operation_id),error:Pt(e.error),receivedAt:String(e.received_at),processedAt:Pt(e.processed_at)}}class Gt{controlPlane;key;nowFn;idFn;constructor(e,t={}){this.controlPlane=e;this.key=t.encryptionKey?Yp("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=Bd(12),r=Yb("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=Xb("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
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?)`,[r,e.organizationId,e.provider,Gp(e.name),Hp(e.host),e.owner?.trim()||null,e.authKind??(n?"access_token":"none"),n?this.encrypt(n):null,n?Wo(n).slice(0,16):null,Ni([...new Set(e.grantedScopes??[])].sort()),Ni(Xp[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:Hp(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=eS(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),Wo(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:Wo(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?Ni(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
|
+
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,jd(e.fullName),Zb(e.cloneUrl),e.defaultBranch.trim()||"main",e.visibility,e.archived?1:0,Ni(e.metadata),r]),Fd(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(Fd)}getRepository(e){let t=this.controlPlane.database.query("SELECT * FROM source_repositories WHERE id = ?").get(e);return t?Fd(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:${Wo(e.publicKey.trim())}`,o=`sha256:${Wo(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,Gp(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}}),Ud(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?Ud(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(Ud)}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)
|
|
5
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, ?)`,[r,e.projectId,e.environmentId??null,e.resourceId??null,e.connectionId,e.repositoryId??null,jd(e.repositoryFullName),e.defaultBranch?.trim()||"main",e.branchRule?.trim()||null,e.tagRule?.trim()||null,Kp(e.monorepoRoot??"."),Ni(Ya(e.includePaths)),Ni(Ya(e.excludePaths)),e.submodules?1:0,e.cloneDepth??null,e.deployKeyId??null,e.autoDeploy===!1?0:1,e.pullRequestPreviews===!1?0:1,e.actorId??null,n,n]),this.controlPlane.appendEvent({organizationId:t.organizationId,projectId:e.projectId,actorId:e.actorId,type:"source.binding.created",payload:{bindingId:r,connectionId:e.connectionId,repository:e.repositoryFullName,branch:e.defaultBranch??"main"}}),this.getBinding(r)}getBinding(e){let t=this.controlPlane.database.query("SELECT * FROM source_bindings WHERE id = ?").get(e);return t?Qp(t):void 0}listBindings(e={}){return this.controlPlane.database.query("SELECT * FROM source_bindings ORDER BY created_at DESC").all().map(Qp).filter((r)=>(!e.connectionId||r.connectionId===e.connectionId)&&(!e.projectId||r.projectId===e.projectId)&&(!e.status||r.status===e.status))}updateBinding(e,t,r){let n=this.getBinding(e);if(!n||n.version!==t)throw Error(`Source binding ${e} changed since version ${t}`);let i=this.getConnection(n.connectionId);if((!i||["disconnected","expired"].includes(i.status))&&(r.status==="active"||r.autoDeploy===!0))throw Error("Rotate or reconnect the source credential before enabling this binding");if(r.deployKeyId&&this.getDeployKey(r.deployKeyId)?.connectionId!==n.connectionId)throw Error("Deploy key does not belong to this connection");let o=this.now();if(this.controlPlane.database.run("UPDATE source_bindings SET default_branch=?, branch_rule=?, tag_rule=?, monorepo_root=?, include_paths=?, exclude_paths=?, submodules=?, clone_depth=?, deploy_key_id=?, auto_deploy=?, pull_request_previews=?, status=?, disabled_reason=?, version=version+1, updated_at=? WHERE id=? AND version=?",[r.defaultBranch?.trim()||n.defaultBranch,r.branchRule===void 0?n.branchRule??null:r.branchRule.trim()||null,r.tagRule===void 0?n.tagRule??null:r.tagRule.trim()||null,r.monorepoRoot===void 0?n.monorepoRoot:Kp(r.monorepoRoot),Ni(r.includePaths===void 0?n.includePaths:Ya(r.includePaths)),Ni(r.excludePaths===void 0?n.excludePaths:Ya(r.excludePaths)),r.submodules??n.submodules?1:0,r.cloneDepth===void 0?n.cloneDepth??null:r.cloneDepth,r.deployKeyId===void 0?n.deployKeyId??null:r.deployKeyId,r.autoDeploy??n.autoDeploy?1:0,r.pullRequestPreviews??n.pullRequestPreviews?1:0,r.status??n.status,r.disabledReason===void 0?n.disabledReason??null:r.disabledReason.slice(0,1000),o,e,t]).changes!==1)throw Error(`Source binding ${e} changed since version ${t}`);let c=this.getConnection(n.connectionId);return this.controlPlane.appendEvent({organizationId:c.organizationId,projectId:n.projectId,actorId:r.actorId,type:"source.binding.updated",payload:{bindingId:e,fromVersion:t,toVersion:t+1,status:r.status??n.status}}),this.getBinding(e)}createWebhook(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");let r=this.idFn(),n=this.now(),i=e.endpointToken??Bd(24).toString("base64url"),o=e.secret??Bd(32).toString("base64url"),s=[...new Set(e.events??["push","pull_request"])].filter((c)=>["push","pull_request"].includes(c));if(!s.length)throw Error("At least one supported webhook event is required");return this.run("INSERT INTO source_webhooks (id, connection_id, repository_id, repository_full_name, endpoint_token_hash, endpoint_token_ciphertext, secret_ciphertext, events, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?)",[r,e.connectionId,e.repositoryId??null,jd(e.repositoryFullName),Wo(i),this.encrypt(i),this.encrypt(o),Ni(s),n,n]),this.controlPlane.appendEvent({organizationId:t.organizationId,type:"source.webhook.created",payload:{webhookId:r,connectionId:t.id,repository:e.repositoryFullName,events:s}}),{webhook:{...this.getWebhook(r),endpointToken:i},secret:o}}getWebhook(e){let t=this.controlPlane.database.query("SELECT * FROM source_webhooks WHERE id = ?").get(e);return t?zd(t):void 0}getWebhookByEndpointToken(e){let t=this.controlPlane.database.query("SELECT * FROM source_webhooks WHERE endpoint_token_hash = ?").get(Wo(e));return t?zd(t):void 0}getWebhookSecret(e){let t=this.controlPlane.database.query("SELECT secret_ciphertext FROM source_webhooks WHERE id = ?").get(e);if(!t)throw Error("Source webhook was not found");return this.decrypt(String(t.secret_ciphertext))}getWebhookEndpointToken(e){let t=this.controlPlane.database.query("SELECT endpoint_token_ciphertext FROM source_webhooks WHERE id = ?").get(e);if(!t?.endpoint_token_ciphertext)throw Error("Source webhook endpoint token is unavailable");return this.decrypt(String(t.endpoint_token_ciphertext))}listWebhooks(e){return this.controlPlane.database.query("SELECT * FROM source_webhooks WHERE connection_id = ? ORDER BY repository_full_name").all(e).map(zd)}updateWebhookState(e,t){let r=this.getWebhook(e);if(!r)throw Error("Source webhook was not found");let n=this.now();this.run("UPDATE source_webhooks SET provider_webhook_id=COALESCE(?, provider_webhook_id), status=?, health_message=?, last_reconciled_at=COALESCE(?, last_reconciled_at), updated_at=? WHERE id=?",[t.providerWebhookId??null,t.status,t.healthMessage?.slice(0,1000)??null,t.reconciled?n:null,n,e]);let i=this.getConnection(r.connectionId);if(i)this.controlPlane.appendEvent({organizationId:i.organizationId,type:"source.webhook.updated",payload:{webhookId:e,connectionId:i.id,repository:r.repositoryFullName,status:t.status,reconciled:t.reconciled??!1,providerWebhookId:t.providerWebhookId??r.providerWebhookId??null}});return this.getWebhook(e)}getDeliveryByProviderId(e,t){let r=this.controlPlane.database.query("SELECT * FROM source_webhook_deliveries WHERE connection_id = ? AND provider_delivery_id = ?").get(e,t);return r?Vd(r):void 0}recordDelivery(e){let t=this.getDeliveryByProviderId(e.connectionId,e.providerDeliveryId);if(t)return{delivery:t,duplicate:!0};let r=this.idFn(),n=this.now();return this.controlPlane.database.transaction(()=>{this.run("INSERT INTO source_webhook_deliveries (id, connection_id, webhook_id, provider_delivery_id, event, action, commit_sha, signature_status, status, payload_summary, operation_id, error, received_at, processed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[r,e.connectionId,e.webhookId,e.providerDeliveryId,e.event.slice(0,100),e.action?.slice(0,100)??null,e.commitSha?.slice(0,128)??null,e.signatureStatus,e.status,Ni(e.payloadSummary??{}),e.operationId??null,e.error?.slice(0,2000)??null,n,["enqueued","ignored","rejected","failed"].includes(e.status)?n:null]),this.run("UPDATE source_webhooks SET last_delivery_at=?, updated_at=? WHERE id=?",[n,n,e.webhookId])})(),{delivery:this.getDeliveryByProviderId(e.connectionId,e.providerDeliveryId),duplicate:!1}}updateDelivery(e,t){this.run("UPDATE source_webhook_deliveries SET status=?, operation_id=?, error=?, processed_at=? WHERE id=?",[t.status,t.operationId??null,t.error?.slice(0,2000)??null,this.now(),e]);let r=this.controlPlane.database.query("SELECT * FROM source_webhook_deliveries WHERE id = ?").get(e);if(!r)throw Error("Source webhook delivery was not found");return Vd(r)}listDeliveries(e,t=100){return this.controlPlane.database.query("SELECT * FROM source_webhook_deliveries WHERE webhook_id = ? ORDER BY received_at DESC LIMIT ?").all(e,Math.min(500,Math.max(1,t))).map(Vd)}disconnectConnection(e,t){let r=this.getConnection(e);if(!r)throw Error("Source connection was not found");let n=this.listBindings({connectionId:e,status:"active"}),i=this.now();return this.controlPlane.database.transaction(()=>{this.run("UPDATE source_connections SET status='disconnected', credential_ciphertext=NULL, health_message='Disconnected by an administrator', version=version+1, updated_at=? WHERE id=?",[i,e]),this.run("UPDATE source_bindings SET status='disabled', auto_deploy=0, disabled_reason='Source connection was disconnected', version=version+1, updated_at=? WHERE connection_id=? AND status='active'",[i,e]),this.run("UPDATE source_webhooks SET status='disabled', health_message='Source connection was disconnected', updated_at=? WHERE connection_id=?",[i,e])})(),this.controlPlane.appendEvent({organizationId:r.organizationId,actorId:t,type:"source.connection.disconnected",level:"warning",payload:{connectionId:e,affectedBindingIds:n.map((o)=>o.id),affectedRepositories:n.map((o)=>o.repositoryFullName)}}),{connection:this.getConnection(e),affectedBindings:n}}}import{createSign as tS}from"node:crypto";class ks extends Error{status;retryAfterSeconds;constructor(e,t,r){super(e);this.status=t;this.retryAfterSeconds=r;this.name="SourceProviderError"}}var eg={repositories:!0,branches:!0,tags:!0,webhooks:!0,pullRequests:!0,tokenRefresh:!0,deployKeys:!0};function So(e){let t=Number(e??"1");return Number.isInteger(t)&&t>0?t:1}function vo(e){return Math.max(1,Math.min(100,e??50))}function ai(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 fa(e){let t=new URL(e);if(t.username||t.password||t.protocol!=="https:")throw Error("Webhook endpoint must be credential-free HTTPS");return t.href}function Zp(e){return Buffer.from(e).toString("base64url")}function rS(e,t){if(!e.appId||!e.privateKey)throw Error("GitHub App credentials require appId and privateKey");let r=Zp(JSON.stringify({alg:"RS256",typ:"JWT"})),n=Math.floor(t.getTime()/1000)-30,i=Zp(JSON.stringify({iat:n,exp:n+540,iss:e.appId})),o=tS("RSA-SHA256");return o.update(`${r}.${i}`),o.end(),`${r}.${i}.${o.sign(e.privateKey).toString("base64url")}`}class ha{connection;credential;capabilities=eg;fetchFn;timeoutMs;nowFn;constructor(e,t,r={}){this.connection=e;this.credential=t;this.fetchFn=r.fetch??((n,i)=>globalThis.fetch(n,i)),this.timeoutMs=Math.max(100,r.timeoutMs??20000),this.nowFn=r.now??(()=>new Date)}async request(e,t={}){let r=new URL(`${this.apiRoot().replace(/\/$/,"")}/`),n=new URL(e.replace(/^\//,""),r);if(n.origin!==r.origin)throw Error("Provider pagination cannot leave the configured host");let i=new AbortController,o=setTimeout(()=>i.abort(),this.timeoutMs);try{let s=await this.fetchFn(n,{...t,redirect:"error",signal:i.signal,headers:{Accept:"application/json","User-Agent":"ts-cloud-source/1",...await this.authorization(),...t.headers}});if(!s.ok){let c=Number(s.headers.get("retry-after")??""),l=s.headers.get("x-request-id")??s.headers.get("x-github-request-id");throw new ks(`Source provider request failed (${s.status})${l?` [request ${l}]`:""}`,s.status,Number.isFinite(c)?c:void 0)}if(s.status===204)return{data:void 0,headers:s.headers};return{data:await s.json(),headers:s.headers}}catch(s){if(s instanceof ks)throw s;if(i.signal.aborted)throw new ks(`Source provider request exceeded ${this.timeoutMs}ms`);throw new ks(s instanceof Error?s.message.replace(/(?:token|password|secret)=[^\s&]+/gi,"$1=[REDACTED]"):"Source provider request failed")}finally{clearTimeout(o)}}async deleteWebhook(e,t){await this.request(this.webhookPath(e,t),{method:"DELETE"})}}class tg extends ha{provider="github";installationToken;apiRoot(){return this.connection.host==="https://github.com"?"https://api.github.com":`${this.connection.host}/api/v3`}async authorization(){if(this.credential?.token)return{Authorization:`Bearer ${this.credential.token}`,"X-GitHub-Api-Version":"2022-11-28"};if(!this.credential?.installationId)return{};if(!this.installationToken||this.installationToken.expiresAt<this.nowFn().getTime()+60000){let e=rS(this.credential,this.nowFn()),t=this.apiRoot().replace(/\/$/,""),r=new AbortController,n=setTimeout(()=>r.abort(),this.timeoutMs);try{let i=await this.fetchFn(`${t}/app/installations/${encodeURIComponent(this.credential.installationId)}/access_tokens`,{method:"POST",signal:r.signal,redirect:"error",headers:{Accept:"application/vnd.github+json",Authorization:`Bearer ${e}`,"X-GitHub-Api-Version":"2022-11-28","User-Agent":"ts-cloud-source/1"}});if(!i.ok)throw new ks(`GitHub App token refresh failed (${i.status})`,i.status);let o=await i.json();this.installationToken={value:o.token,expiresAt:new Date(o.expires_at).getTime()}}finally{clearTimeout(n)}}return{Authorization:`Bearer ${this.installationToken.value}`,"X-GitHub-Api-Version":"2022-11-28"}}async testConnection(){let e=this.credential?.installationId?"/installation/repositories?per_page=1":"/user",{data:t,headers:r}=await this.request(e);return{ok:!0,account:t.login??this.connection.owner,scopes:(r.get("x-oauth-scopes")??this.connection.grantedScopes.join(",")).split(",").map((n)=>n.trim()).filter(Boolean),message:"GitHub connection is healthy"}}async listRepositories(e={}){let t=vo(e.limit),r=So(e.cursor),n=this.credential?.installationId?`/installation/repositories?per_page=${t}&page=${r}`:`/user/repos?per_page=${t}&page=${r}&sort=updated`,{data:i}=await this.request(n),o=Array.isArray(i)?i:i.repositories;return{repositories:(e.search?o.filter((c)=>c.full_name.toLowerCase().includes(e.search.toLowerCase())):o).map((c)=>({providerRepositoryId:String(c.id),fullName:c.full_name,cloneUrl:c.clone_url,defaultBranch:c.default_branch||"main",visibility:c.visibility??(c.private?"private":"public"),archived:!!c.archived,metadata:{}})),nextCursor:o.length===t?String(r+1):void 0}}async refs(e,t,r={}){let n=vo(r.limit),i=So(r.cursor),{data:o}=await this.request(`/repos/${ai(e)}/${t}?per_page=${n}&page=${i}`);return{refs:o.map((s)=>({name:s.name,commitSha:s.commit.sha,protected:s.protected})),nextCursor:o.length===n?String(i+1):void 0}}listBranches(e,t){return this.refs(e,"branches",t)}listTags(e,t){return this.refs(e,"tags",t)}webhookPath(e,t){return`/repos/${ai(e)}/hooks${t?`/${encodeURIComponent(t)}`:""}`}hook(e){return{providerWebhookId:String(e.id),active:e.active,events:e.events,url:e.config.url??""}}async createWebhook(e,t){let{data:r}=await this.request(this.webhookPath(e),{method:"POST",body:JSON.stringify({name:"web",active:!0,events:t.events,config:{url:fa(t.url),content_type:"json",secret:t.secret,insecure_ssl:"0"}}),headers:{"Content-Type":"application/json"}});return this.hook(r)}async listWebhooks(e){let{data:t}=await this.request(this.webhookPath(e));return t.map((r)=>this.hook(r))}async updateWebhook(e,t,r){let{data:n}=await this.request(this.webhookPath(e,t),{method:"PATCH",body:JSON.stringify({active:!0,events:r.events,config:{url:fa(r.url),content_type:"json",secret:r.secret,insecure_ssl:"0"}}),headers:{"Content-Type":"application/json"}});return this.hook(n)}async setCommitStatus(e,t,r){await this.request(`/repos/${ai(e)}/statuses/${encodeURIComponent(t)}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:r.state,target_url:r.url,description:r.description.slice(0,140),context:r.context??"ts-cloud/preview"})})}}class rg extends ha{provider="gitlab";apiRoot(){return`${this.connection.host}/api/v4`}async authorization(){return this.credential?.token?{"PRIVATE-TOKEN":this.credential.token}:{}}async testConnection(){let{data:e}=await this.request("/user");return{ok:!0,account:e.username,scopes:this.connection.grantedScopes,message:"GitLab connection is healthy"}}async listRepositories(e={}){let t=vo(e.limit),r=So(e.cursor),n=e.search?`&search=${encodeURIComponent(e.search)}`:"",{data:i,headers:o}=await this.request(`/projects?membership=true&simple=true&order_by=last_activity_at&per_page=${t}&page=${r}${n}`);return{repositories:i.map((s)=>({providerRepositoryId:String(s.id),fullName:s.path_with_namespace,cloneUrl:s.http_url_to_repo,defaultBranch:s.default_branch??"main",visibility:s.visibility??"unknown",archived:!!s.archived,metadata:{}})),nextCursor:o.get("x-next-page")||void 0}}async refs(e,t,r={}){let n=vo(r.limit),i=So(r.cursor),{data:o,headers:s}=await this.request(`/projects/${encodeURIComponent(ai(e))}/repository/${t}?per_page=${n}&page=${i}`);return{refs:o.map((c)=>({name:c.name,commitSha:c.commit.id,protected:c.protected})),nextCursor:s.get("x-next-page")||void 0}}listBranches(e,t){return this.refs(e,"branches",t)}listTags(e,t){return this.refs(e,"tags",t)}webhookPath(e,t){return`/projects/${encodeURIComponent(ai(e))}/hooks${t?`/${encodeURIComponent(t)}`:""}`}hook(e){return{providerWebhookId:String(e.id),active:!0,events:[...e.push_events?["push"]:[],...e.merge_requests_events?["pull_request"]:[]],url:e.url}}body(e){return JSON.stringify({url:fa(e.url),token:e.secret,enable_ssl_verification:!0,push_events:e.events.includes("push"),merge_requests_events:e.events.includes("pull_request")})}async createWebhook(e,t){let{data:r}=await this.request(this.webhookPath(e),{method:"POST",body:this.body(t),headers:{"Content-Type":"application/json"}});return this.hook(r)}async listWebhooks(e){let{data:t}=await this.request(this.webhookPath(e));return t.map((r)=>this.hook(r))}async updateWebhook(e,t,r){let{data:n}=await this.request(this.webhookPath(e,t),{method:"PUT",body:this.body(r),headers:{"Content-Type":"application/json"}});return this.hook(n)}async setCommitStatus(e,t,r){let n=r.state==="failure"||r.state==="error"?"failed":r.state;await this.request(`/projects/${encodeURIComponent(ai(e))}/statuses/${encodeURIComponent(t)}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:n,target_url:r.url,description:r.description.slice(0,255),name:r.context??"ts-cloud/preview"})})}}class ng extends ha{provider="bitbucket";apiRoot(){return this.connection.host==="https://bitbucket.org"?"https://api.bitbucket.org/2.0":`${this.connection.host}/2.0`}async authorization(){return this.credential?.token?{Authorization:`Bearer ${this.credential.token}`}:{}}async testConnection(){let{data:e}=await this.request("/user");return{ok:!0,account:e.username??e.display_name,scopes:this.connection.grantedScopes,message:"Bitbucket connection is healthy"}}async listRepositories(e={}){if(!this.connection.owner)throw Error("Bitbucket repository discovery requires an owner/workspace");let t=So(e.cursor),r=vo(e.limit),n=e.search?`&q=name~%22${encodeURIComponent(e.search)}%22`:"",{data:i}=await this.request(`/repositories/${encodeURIComponent(this.connection.owner)}?pagelen=${r}&page=${t}${n}`);return{repositories:i.values.map((o)=>({providerRepositoryId:o.uuid,fullName:o.full_name,cloneUrl:o.links.clone.find((s)=>s.name==="https")?.href??o.links.clone[0]?.href??"",defaultBranch:o.mainbranch?.name??"main",visibility:o.is_private?"private":"public",archived:!1,metadata:{}})),nextCursor:i.next?String(t+1):void 0}}async refs(e,t,r={}){let n=So(r.cursor),i=vo(r.limit),{data:o}=await this.request(`/repositories/${ai(e)}/refs/${t}?pagelen=${i}&page=${n}`);return{refs:o.values.map((s)=>({name:s.name,commitSha:s.target.hash})),nextCursor:o.next?String(n+1):void 0}}listBranches(e,t){return this.refs(e,"branches",t)}listTags(e,t){return this.refs(e,"tags",t)}webhookPath(e,t){return`/repositories/${ai(e)}/hooks${t?`/${encodeURIComponent(t)}`:""}`}hook(e){return{providerWebhookId:e.uuid,active:e.active,events:e.events.map((t)=>t.replace("repo:push","push").replace("pullrequest:","pull_request:")),url:e.url}}body(e){return JSON.stringify({description:"ts-cloud deploy",url:fa(e.url),active:!0,events:e.events.map((t)=>t==="push"?"repo:push":t.replace("pull_request:","pullrequest:"))})}async createWebhook(e,t){let{data:r}=await this.request(this.webhookPath(e),{method:"POST",body:this.body(t),headers:{"Content-Type":"application/json"}});return this.hook(r)}async listWebhooks(e){let{data:t}=await this.request(this.webhookPath(e));return t.values.map((r)=>this.hook(r))}async updateWebhook(e,t,r){let{data:n}=await this.request(this.webhookPath(e,t),{method:"PUT",body:this.body(r),headers:{"Content-Type":"application/json"}});return this.hook(n)}async setCommitStatus(e,t,r){let n=r.state==="success"?"SUCCESSFUL":r.state==="pending"?"INPROGRESS":"FAILED";await this.request(`/repositories/${ai(e)}/commit/${encodeURIComponent(t)}/statuses/build/ts-cloud-preview`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:n,key:"ts-cloud-preview",name:r.context??"ts-cloud/preview",url:r.url,description:r.description.slice(0,255)})})}}class ig extends ha{provider="gitea";capabilities={...eg,tokenRefresh:!1};apiRoot(){return`${this.connection.host}/api/v1`}async authorization(){return this.credential?.token?{Authorization:`token ${this.credential.token}`}:{}}async testConnection(){let{data:e}=await this.request("/user");return{ok:!0,account:e.login,scopes:this.connection.grantedScopes,message:"Gitea connection is healthy"}}async listRepositories(e={}){let t=So(e.cursor),r=vo(e.limit),n=e.search?`/repos/search?q=${encodeURIComponent(e.search)}&limit=${r}&page=${t}`:`/user/repos?limit=${r}&page=${t}`,{data:i,headers:o}=await this.request(n),s=Array.isArray(i)?i:i.data;return{repositories:s.map((c)=>({providerRepositoryId:String(c.id),fullName:c.full_name,cloneUrl:c.clone_url,defaultBranch:c.default_branch??"main",visibility:c.private?"private":"public",archived:!!c.archived,metadata:{}})),nextCursor:o.get("x-hasmore")==="true"||s.length===r?String(t+1):void 0}}async refs(e,t,r={}){let n=So(r.cursor),i=vo(r.limit),{data:o}=await this.request(`/repos/${ai(e)}/${t}?limit=${i}&page=${n}`);return{refs:o.map((s)=>({name:s.name,commitSha:s.commit.id})),nextCursor:o.length===i?String(n+1):void 0}}listBranches(e,t){return this.refs(e,"branches",t)}listTags(e,t){return this.refs(e,"tags",t)}webhookPath(e,t){return`/repos/${ai(e)}/hooks${t?`/${encodeURIComponent(t)}`:""}`}hook(e){return{providerWebhookId:String(e.id),active:e.active,events:e.events??[],url:e.config.url??""}}body(e){return JSON.stringify({type:"gitea",active:!0,events:e.events,config:{url:fa(e.url),content_type:"json",secret:e.secret,insecure_ssl:"0"}})}async createWebhook(e,t){let{data:r}=await this.request(this.webhookPath(e),{method:"POST",body:this.body(t),headers:{"Content-Type":"application/json"}});return this.hook(r)}async listWebhooks(e){let{data:t}=await this.request(this.webhookPath(e));return t.map((r)=>this.hook(r))}async updateWebhook(e,t,r){let{data:n}=await this.request(this.webhookPath(e,t),{method:"PATCH",body:this.body(r),headers:{"Content-Type":"application/json"}});return this.hook(n)}async setCommitStatus(e,t,r){await this.request(`/repos/${ai(e)}/statuses/${encodeURIComponent(t)}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:r.state,target_url:r.url,description:r.description.slice(0,140),context:r.context??"ts-cloud/preview"})})}}function wo(e,t,r={}){switch(e.provider){case"github":return new tg(e,t,r);case"gitlab":return new rg(e,t,r);case"bitbucket":return new ng(e,t,r);case"gitea":return new ig(e,t,r);default:throw Error(`${e.provider} uses bounded Git discovery instead of a hosted provider API`)}}import{createHmac as nS,timingSafeEqual as iS}from"node:crypto";function nn(e,t){if(e instanceof Headers)return e.get(t)??void 0;return Object.entries(e).find(([n])=>n.toLowerCase()===t.toLowerCase())?.[1]}function og(e,t){let r=Buffer.from(e),n=Buffer.from(t);return r.length===n.length&&iS(r,n)}function oS(e,t){return nS("sha256",e).update(t).digest("hex")}function sS(e,t,r,n,i){if(e==="gitlab")return og(nn(r,"x-gitlab-token")??"",t);let o=e==="github"?nn(r,"x-hub-signature-256"):e==="gitea"?nn(r,"x-gitea-signature"):nn(r,"x-hub-signature")??nn(r,"x-ts-cloud-signature");if(!o)return!1;if(e==="generic_https"||e==="generic_ssh"){let s=Number(nn(r,"x-ts-cloud-timestamp"));if(!Number.isFinite(s)||Math.abs(i.getTime()-s*1000)>300000)return!1}return og(o.replace(/^sha256=/,""),oS(t,n))}function aS(e,t){return{github:["x-github-delivery"],gitlab:["x-gitlab-event-uuid","x-request-id"],bitbucket:["x-request-uuid"],gitea:["x-gitea-delivery"],generic_https:["x-ts-cloud-delivery"],generic_ssh:["x-ts-cloud-delivery"]}[e].map((n)=>nn(t,n)?.trim()).find(Boolean)}function Io(e){let t=String(e??"").trim().replace(/^\/+|\/+$/g,"");return/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(t)?t:""}function qd(e){return[...new Set(e.flatMap((t)=>{if(!t||typeof t!=="object")return[];let r=t;return[...r.added??[],...r.modified??[],...r.removed??[]].map(String)}).filter((t)=>t&&!t.includes("\x00")).slice(0,500))]}function cS(e,t,r){let n=e,i=t,o=r;if(n==="github"){let s=nn(i,"x-github-event"),c=Io(o.repository?.full_name);if(s==="push")return{event:"push",repository:c,ref:String(o.ref??""),branch:String(o.ref??"").replace(/^refs\/heads\//,""),tag:String(o.ref??"").startsWith("refs/tags/")?String(o.ref).replace(/^refs\/tags\//,""):void 0,commitSha:String(o.after??o.head_commit?.id??""),changedPaths:qd(o.commits??[]),deleted:o.deleted===!0||/^0{40,64}$/.test(String(o.after??""))};if(s==="pull_request")return{event:"pull_request",action:String(o.action??""),repository:c,branch:String(o.pull_request?.head?.ref??""),commitSha:String(o.pull_request?.head?.sha??""),changedPaths:[],pullRequestNumber:Number(o.number)||void 0,fork:Io(o.pull_request?.head?.repo?.full_name)!==c}}if(n==="gitlab"){let s=String(o.object_kind??"").toLowerCase(),c=Io(o.project?.path_with_namespace);if(s==="push"||s==="tag_push")return{event:"push",repository:c,ref:String(o.ref??""),branch:String(o.ref??"").replace(/^refs\/heads\//,""),tag:s==="tag_push"?String(o.ref??"").replace(/^refs\/tags\//,""):void 0,commitSha:String(o.checkout_sha??o.after??""),changedPaths:qd(o.commits??[]),deleted:/^0{40,64}$/.test(String(o.after??""))};if(s==="merge_request")return{event:"pull_request",action:String(o.object_attributes?.action??o.object_attributes?.state??""),repository:c,branch:String(o.object_attributes?.source_branch??""),commitSha:String(o.object_attributes?.last_commit?.id??""),changedPaths:[],pullRequestNumber:Number(o.object_attributes?.iid)||void 0,fork:o.object_attributes?.source_project_id!==o.object_attributes?.target_project_id}}if(n==="bitbucket"){let s=nn(i,"x-event-key")??"",c=Io(o.repository?.full_name);if(s==="repo:push"){let l=o.push?.changes?.[0]??{},a=l.new??l.old??{},m=l.new?.target??l.old?.target;return{event:"push",repository:c,ref:String(a.name??""),branch:a.type==="branch"?String(a.name):void 0,tag:a.type==="tag"?String(a.name):void 0,commitSha:String(m?.hash??""),changedPaths:[],deleted:l.closed===!0||l.new==null}}if(s.startsWith("pullrequest:"))return{event:"pull_request",action:s.replace("pullrequest:",""),repository:c,branch:String(o.pullrequest?.source?.branch?.name??""),commitSha:String(o.pullrequest?.source?.commit?.hash??""),changedPaths:[],pullRequestNumber:Number(o.pullrequest?.id)||void 0,fork:Io(o.pullrequest?.source?.repository?.full_name)!==c}}if(n==="gitea"){let s=nn(i,"x-gitea-event"),c=Io(o.repository?.full_name);if(s==="push")return{event:"push",repository:c,ref:String(o.ref??""),branch:String(o.ref??"").replace(/^refs\/heads\//,""),tag:String(o.ref??"").startsWith("refs/tags/")?String(o.ref).replace(/^refs\/tags\//,""):void 0,commitSha:String(o.after??""),changedPaths:qd(o.commits??[]),deleted:o.deleted===!0||/^0{40,64}$/.test(String(o.after??""))};if(s==="pull_request")return{event:"pull_request",action:String(o.action??""),repository:c,branch:String(o.pull_request?.head?.ref??""),commitSha:String(o.pull_request?.head?.sha??""),changedPaths:[],pullRequestNumber:Number(o.number)||void 0,fork:Io(o.pull_request?.head?.repo?.full_name)!==c}}if(n==="generic_https"||n==="generic_ssh"){if(o.event!=="push"&&o.event!=="pull_request")return;return{event:o.event,action:typeof o.action==="string"?o.action:void 0,repository:Io(o.repository),ref:typeof o.ref==="string"?o.ref:void 0,branch:typeof o.branch==="string"?o.branch:void 0,tag:typeof o.tag==="string"?o.tag:void 0,commitSha:String(o.commitSha??""),changedPaths:Array.isArray(o.changedPaths)?o.changedPaths.map(String).slice(0,500):[],pullRequestNumber:Number(o.pullRequestNumber)||void 0,fork:o.fork===!0,deleted:o.deleted===!0}}return}function Rs(e,t){let r="^";for(let n=0;n<t.length;n++){let i=t[n];if(i==="*"&&t[n+1]==="*")r+=".*",n++;else if(i==="*")r+="[^/]*";else if(i==="?")r+="[^/]";else r+=i.replace(/[|\\{}()[\]^$+?.]/g,"\\$&")}return new RegExp(`${r}$`).test(e)}function dS(e,t){if(t.event==="pull_request")return e.pullRequestPreviews;if(!e.autoDeploy)return!1;if(t.tag)return!!e.tagRule&&Rs(t.tag,e.tagRule);return Rs(t.branch??"",e.branchRule??e.defaultBranch)}function uS(e,t){if(!t.length)return!0;return t.filter((n)=>!e.excludePaths.some((i)=>Rs(n,i))).some((n)=>!e.includePaths.length||e.includePaths.some((i)=>Rs(n,i)))}function sg(e,t){return nn(t,e==="github"?"x-github-event":e==="gitlab"?"x-gitlab-event":e==="bitbucket"?"x-event-key":e==="gitea"?"x-gitea-event":"x-ts-cloud-event")??"unknown"}function Go(){return{accepted:!1,duplicate:!1,status:"rejected",operations:[],message:"Webhook unavailable"}}async function ag(e){if(e.rawBody.byteLength>2097152)return Go();let t=e.sources.getWebhookByEndpointToken(e.endpointToken);if(!t||t.status==="disabled")return Go();let r=e.sources.getConnection(t.connectionId);if(!r||r.status==="disconnected"||r.status==="expired")return Go();let n=aS(r.provider,e.headers);if(!n||n.length>200)return Go();if(!sS(r.provider,e.sources.getWebhookSecret(t.id),e.headers,e.rawBody,e.now??new Date))return e.sources.recordDelivery({connectionId:r.id,webhookId:t.id,providerDeliveryId:n,event:sg(r.provider,e.headers),signatureStatus:nn(e.headers,"x-hub-signature-256")||nn(e.headers,"x-gitlab-token")||nn(e.headers,"x-hub-signature")||nn(e.headers,"x-gitea-signature")?"invalid":"missing",status:"rejected",error:"Webhook signature verification failed"}),Go();let o;try{o=JSON.parse(new TextDecoder().decode(e.rawBody))}catch{return Go()}let s=cS(r.provider,e.headers,o);if(!s||!s.repository||!/^[a-f0-9]{7,64}$/i.test(s.commitSha))return e.sources.recordDelivery({connectionId:r.id,webhookId:t.id,providerDeliveryId:n,event:sg(r.provider,e.headers),signatureStatus:"verified",status:"rejected",error:"Unsupported or malformed source event"}),Go();let c=e.sources.recordDelivery({connectionId:r.id,webhookId:t.id,providerDeliveryId:n,event:s.event,action:s.action,commitSha:s.commitSha,signatureStatus:"verified",status:"accepted",payloadSummary:{repository:s.repository,ref:s.ref??null,branch:s.branch??null,tag:s.tag??null,commitSha:s.commitSha,pullRequestNumber:s.pullRequestNumber??null,changedPathCount:s.changedPaths.length}});if(c.duplicate&&c.delivery.status!=="accepted")return{accepted:!0,duplicate:!0,status:"duplicate",operations:[],message:"Delivery already processed"};let l=new $e(e.controlPlane),a=e.sources.listBindings({connectionId:r.id,status:"active"}).filter((O)=>{if(O.repositoryFullName.toLowerCase()!==s.repository.toLowerCase()||!uS(O,s.changedPaths))return!1;let q=O.resourceId?l.getDefinitionForResource(O.resourceId):void 0,G=s.event==="push"&&!!q?.branchRule&&!!s.branch&&Rs(s.branch,q.branchRule);return dS(O,s)||G});if(!a.length)return e.sources.updateDelivery(c.delivery.id,{status:"ignored"}),{accepted:!0,duplicate:c.duplicate,status:"ignored",operations:[],message:"Verified event did not match an active deployment rule"};let m=new b(e.controlPlane),E=new Set(["closed","merged","declined"]),k=a.flatMap((O)=>{if(s.event==="push"&&O.resourceId&&s.branch){let G=l.getDefinitionForResource(O.resourceId);if(G?.branchRule&&Rs(s.branch,G.branchRule)){let Y=l.findForBranch(G.id,s.repository,s.branch);if(s.deleted){if(!G.cleanupOnClose||!Y||Y.status==="destroyed")return[];let Re=m.enqueue({projectId:O.projectId,environmentId:O.environmentId,resourceId:O.resourceId,kind:"preview.destroy",idempotencyKey:`preview:${Y.id}:branch-delete:${n}`,correlationId:`preview:${Y.id}`,input:{previewId:Y.id,reason:"branch_deleted",source:{repository:s.repository,commitSha:s.commitSha,branch:s.branch}},lockKey:`preview:${Y.id}`,providerKey:r.provider,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return l.transition(Y.id,"queued",{operationId:Re.id}),[Re]}let re=l.upsert({definitionId:G.id,sourceProvider:r.provider,repository:s.repository,branch:s.branch,commitSha:s.commitSha});if(!re.changed)return[];let he=re.created?"preview.create":"preview.update",ee=m.enqueue({projectId:O.projectId,environmentId:O.environmentId,resourceId:O.resourceId,kind:he,idempotencyKey:`preview:${re.preview.id}:${s.commitSha}`,correlationId:`preview:${re.preview.id}`,input:{previewId:re.preview.id,source:{connectionId:r.id,bindingId:O.id,repository:s.repository,commitSha:s.commitSha,branch:s.branch,monorepoRoot:O.monorepoRoot,submodules:O.submodules,cloneDepth:O.cloneDepth??null}},lockKey:`preview:${re.preview.id}`,providerKey:r.provider,buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return l.transition(re.preview.id,"queued",{operationId:ee.id}),[ee]}}if(s.event==="pull_request"&&O.resourceId&&s.pullRequestNumber){let G=l.getDefinitionForResource(O.resourceId);if(G){let Y=E.has(String(s.action??"").toLowerCase()),re=l.findForPullRequest(G.id,s.repository,s.pullRequestNumber);if(Y){if(!G.cleanupOnClose||!re||re.status==="destroyed")return[];let he=m.enqueue({projectId:O.projectId,environmentId:O.environmentId,resourceId:O.resourceId,kind:"preview.destroy",idempotencyKey:`preview:${re.id}:destroy:${n}`,correlationId:`preview:${re.id}`,input:{previewId:re.id,reason:"pull_request_closed",source:{repository:s.repository,commitSha:s.commitSha,branch:s.branch??null,pullRequestNumber:s.pullRequestNumber}},lockKey:`preview:${re.id}`,providerKey:r.provider,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return l.transition(re.id,"queued",{operationId:he.id}),[he]}try{let he=l.upsert({definitionId:G.id,sourceProvider:r.provider,repository:s.repository,branch:s.branch??`pr-${s.pullRequestNumber}`,pullRequestNumber:s.pullRequestNumber,fork:s.fork,commitSha:s.commitSha});if(!he.changed)return[];let ee=he.created?"preview.create":"preview.update",Re=m.enqueue({projectId:O.projectId,environmentId:O.environmentId,resourceId:O.resourceId,kind:ee,idempotencyKey:`preview:${he.preview.id}:${s.commitSha}`,correlationId:`preview:${he.preview.id}`,input:{previewId:he.preview.id,source:{connectionId:r.id,bindingId:O.id,repository:s.repository,commitSha:s.commitSha,branch:s.branch??null,pullRequestNumber:s.pullRequestNumber,fork:!!s.fork,monorepoRoot:O.monorepoRoot,submodules:O.submodules,cloneDepth:O.cloneDepth??null},inheritedSecretNames:he.inheritedSecrets},lockKey:`preview:${he.preview.id}`,providerKey:r.provider,buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return l.transition(he.preview.id,"queued",{operationId:Re.id}),[Re]}catch(he){return e.controlPlane.appendEvent({projectId:O.projectId,resourceId:O.resourceId,type:"preview.rejected",level:"warning",payload:{repository:s.repository,pullRequestNumber:s.pullRequestNumber,fork:!!s.fork,reason:he instanceof Error?he.message:String(he)}}),[]}}}let q=s.event==="pull_request"?"deploy.preview":"deploy.source";return[m.enqueue({projectId:O.projectId,environmentId:O.environmentId,resourceId:O.resourceId,kind:q,idempotencyKey:`source:${r.id}:${n}:${O.id}:${s.commitSha}`,correlationId:`source:${n}`,input:{source:{connectionId:r.id,bindingId:O.id,repository:s.repository,commitSha:s.commitSha,branch:s.branch??null,tag:s.tag??null,monorepoRoot:O.monorepoRoot,submodules:O.submodules,cloneDepth:O.cloneDepth??null},preview:s.event==="pull_request"?{number:s.pullRequestNumber??null,action:s.action??null}:null},lockKey:O.resourceId?`resource:${O.resourceId}`:`environment:${O.environmentId??O.projectId}`,providerKey:r.provider,buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:s.event==="pull_request"?14:90}).operation]});if(!k.length)return e.sources.updateDelivery(c.delivery.id,{status:"ignored"}),{accepted:!0,duplicate:c.duplicate,status:"ignored",operations:[],message:"Verified event required no preview lifecycle change"};return e.sources.updateDelivery(c.delivery.id,{status:"enqueued",operationId:k[0]?.id}),e.controlPlane.appendEvent({organizationId:r.organizationId,projectId:a[0]?.projectId,operationId:k[0]?.id,type:"source.webhook.enqueued",payload:{webhookId:t.id,deliveryId:c.delivery.id,repository:s.repository,commitSha:s.commitSha,operationIds:k.map((O)=>O.id)}}),{accepted:!0,duplicate:c.duplicate,status:"enqueued",operations:k,message:`${k.length} deployment operation${k.length===1?"":"s"} enqueued`}}function Ct(e,t){if(!t.endpointToken)throw Error("The webhook endpoint token is only available at creation time");let r=new URL(e);if(r.protocol!=="https:"&&!["localhost","127.0.0.1","::1"].includes(r.hostname))throw Error("Webhook base URL must use HTTPS");return new URL(`/api/source/webhooks/${encodeURIComponent(t.endpointToken)}`,r).href}import{chmodSync as cg,mkdtempSync as lS,rmSync as pS,writeFileSync as dg}from"node:fs";import{tmpdir as gS}from"node:os";import{join as Xa,resolve as mS}from"node:path";function lg(e,t){let r=e.trim();if(/\r|\n|\0/.test(r))throw Error("Git remote contains control characters");if(r.startsWith("https://")){let i=new URL(r);if(i.username||i.password||i.search||i.hash)throw Error("HTTPS Git remotes cannot contain credentials, queries, or fragments");return i.href}let n=r.startsWith("ssh://")?new URL(r).hostname:r.match(/^git@([A-Za-z0-9.-]+):/)?.[1];if(!n)throw Error("Git remote must use credential-free HTTPS or SSH");if(!t||t.host.toLowerCase()!==n.toLowerCase())throw Error("SSH Git remote requires a deploy key with a pinned key for the same host");return r}function fS(e,t,r){let n=e.replaceAll(t,"[REMOTE]").slice(0,4000);for(let i of[r?.token,r?.privateKey])if(i)n=n.replaceAll(i,"[REDACTED]");return n}function hS(e){let t={PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",HOME:"/nonexistent",GIT_TERMINAL_PROMPT:"0",GIT_CONFIG_NOSYSTEM:"1",GIT_OPTIONAL_LOCKS:"0"},r;if(e.credential?.token){let n=e.credential.username??"oauth2";t.GIT_CONFIG_COUNT="1",t.GIT_CONFIG_KEY_0="http.extraHeader",t.GIT_CONFIG_VALUE_0=`Authorization: Basic ${Buffer.from(`${n}:${e.credential.token}`).toString("base64")}`}if(e.deployKey){r=lS(Xa(gS(),"ts-cloud-git-transport-"));let n=Xa(r,"key"),i=Xa(r,"known_hosts");dg(n,e.deployKey.privateKey,{mode:384}),dg(i,`${e.deployKey.host} ${e.deployKey.hostKey}
|
|
6
|
+
`,{mode:384}),cg(n,384),cg(i,384),t.GIT_SSH_COMMAND=`ssh -i ${n} -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=${i} -o GlobalKnownHostsFile=/dev/null -o BatchMode=yes`}return{env:t,cleanup:()=>{if(r)pS(r,{recursive:!0,force:!0})}}}async function Yo(e,t,r){let n=hS(r),i=Bun.spawn([r.executable??"git",...e],{stdout:"pipe",stderr:"pipe",env:n.env}),o=Math.max(100,r.timeoutMs??120000),s,c=new Promise((l,a)=>{s=setTimeout(()=>{i.kill(),a(Error(`Git operation exceeded ${o}ms`))},o)});try{let l=Promise.all([i.exited,new Response(i.stdout).text(),new Response(i.stderr).text()]),[a,m,E]=await Promise.race([l,c]);if(a!==0)throw Error(fS(E||`Git exited with ${a}`,t,r.credential));return m}finally{if(s)clearTimeout(s);n.cleanup()}}function ug(e,t){let r=new Map;for(let n of e.split(`
|
|
7
|
+
`)){let i=n.trim().match(/^([a-f0-9]{40,64})\s+(.+)$/i);if(!i||!i[2].startsWith(t)||i[2].endsWith("^{}"))continue;let o=i[2].slice(t.length);r.set(o,{name:o,commitSha:i[1]})}return[...r.values()].sort((n,i)=>n.name.localeCompare(i.name))}async function Jd(e,t={}){let r=lg(e,t.deployKey),n=await Yo(["ls-remote","--heads","--tags","--",r],r,t);return{branches:ug(n,"refs/heads/"),tags:ug(n,"refs/tags/")}}async function Wd(e,t={}){let r=lg(e.remote,t.deployKey),n=mS(e.destination),i=e.ref?.trim()||e.binding.defaultBranch;if(!/^[A-Za-z0-9._/-]{1,255}$/.test(i)||i.startsWith("-")||i.includes(".."))throw Error("Git ref contains unsupported characters");let o=["clone","--no-tags","--single-branch","--branch",i],s=[...new Set(e.sparsePaths??[])];if(s.some((l)=>!l||l.startsWith("/")||l.split("/").includes("..")||/[\0\r\n]/.test(l)))throw Error("Sparse checkout paths must stay inside the repository");if(s.length)o.push("--filter=blob:none","--no-checkout");if(e.binding.cloneDepth)o.push("--depth",String(e.binding.cloneDepth));if(e.binding.submodules)o.push("--recurse-submodules","--shallow-submodules");if(o.push("--",r,n),await Yo(o,r,t),s.length)await Yo(["-C",n,"sparse-checkout","set","--cone","--",...s],r,t),await Yo(["-C",n,"checkout","--force"],r,t);if(e.commitSha){if(!/^[a-f0-9]{40,64}$/i.test(e.commitSha))throw Error("Expected source commit must be an immutable 40-64 character SHA");await Yo(["-C",n,"fetch","--no-tags","--depth","1","origin",e.commitSha],r,t),await Yo(["-C",n,"checkout","--detach","--force",e.commitSha],r,t)}let c=(await Yo(["-C",n,"rev-parse","HEAD"],r,t)).trim();if(!/^[a-f0-9]{40,64}$/i.test(c))throw Error("Git clone did not produce a valid commit SHA");if(e.commitSha&&c.toLowerCase()!==e.commitSha.toLowerCase())throw Error(`Git checkout resolved ${c} instead of the requested immutable commit`);return{directory:e.binding.monorepoRoot==="."?n:Xa(n,e.binding.monorepoRoot),commitSha:c}}function ya(e){return["github","gitlab","bitbucket","gitea"].includes(e)}async function Hd(e,t,r){let n=e.getConnection(t);if(!n||["disconnected","expired"].includes(n.status))throw Error("Active source connection was not found");try{if(ya(n.provider)){let s=await wo(n,e.getCredential(n.id)).testConnection();return e.updateHealth(n.id,{status:s.ok?"healthy":"degraded",message:s.message,tested:!0,grantedScopes:s.scopes})}let i=r?e.getRepository(r):e.listRepositories(n.id,void 0,1)[0];if(!i)return e.updateHealth(n.id,{status:"degraded",message:"Add a repository URL before testing this generic connection.",tested:!0});let o=n.provider==="generic_ssh"?e.listBindings({connectionId:n.id}).map((s)=>s.deployKeyId).filter(Boolean).map((s)=>e.getDeployKey(s)).find(Boolean):void 0;return await Jd(i.cloneUrl,{credential:e.getCredential(n.id),deployKey:o?{...o,privateKey:e.getDeployPrivateKey(o.id)}:void 0}),e.updateHealth(n.id,{status:"healthy",message:"Git repository access is healthy.",tested:!0})}catch(i){return e.updateHealth(n.id,{status:"degraded",message:i instanceof Error?i.message:"Connection test failed",tested:!0})}}async function Pr(e,t,r={}){let n=e.getConnection(t);if(!n||!ya(n.provider)||["disconnected","expired"].includes(n.status))throw Error("A hosted active source connection is required for repository discovery");let i=wo(n,e.getCredential(n.id)),o=[],s;for(let c=0;c<Math.min(20,Math.max(1,r.maxPages??10));c++){let l=await i.listRepositories({cursor:s,search:r.search,limit:100});for(let a of l.repositories)o.push(e.upsertRepository({connectionId:n.id,...a}));if(s=l.nextCursor,!s)break}return e.updateHealth(n.id,{status:"healthy",message:`${o.length} repositories synchronized.`,synced:!0}),o}async function Kt(e,t){let r=e.getConnection(t.connectionId);if(!r||["disconnected","expired"].includes(r.status))throw Error("Active source connection was not found");if(ya(r.provider)){let c=wo(r,e.getCredential(r.id));return t.type==="tags"?c.listTags(t.repository,t):c.listBranches(t.repository,t)}let n=t.repositoryId?e.getRepository(t.repositoryId):e.listRepositories(r.id).find((c)=>c.fullName===t.repository);if(!n||n.connectionId!==r.id)throw Error("Generic repository metadata was not found");let i=t.deployKeyId?e.getDeployKey(t.deployKeyId):void 0;if(i&&i.connectionId!==r.id)throw Error("Deploy key does not belong to this connection");let o=await Jd(n.cloneUrl,{credential:e.getCredential(r.id),deployKey:i?{...i,privateKey:e.getDeployPrivateKey(i.id)}:void 0});return{refs:(t.type==="tags"?o.tags:o.branches).slice(0,Math.min(500,t.limit??100))}}async function Jt(e,t,r){let n=e.getWebhook(t),i=n?e.getConnection(n.connectionId):void 0;if(!n||!i||["disconnected","expired"].includes(i.status))throw Error("Active source webhook was not found");let o=Ct(r,{...n,endpointToken:e.getWebhookEndpointToken(n.id)});if(!ya(i.provider))return e.updateWebhookState(n.id,{status:"healthy",healthMessage:"Manual webhook endpoint is ready.",reconciled:!0});try{let s=wo(i,e.getCredential(i.id)),c=e.getWebhookSecret(n.id),l=n.providerWebhookId?await s.updateWebhook(n.repositoryFullName,n.providerWebhookId,{url:o,secret:c,events:n.events}):await s.createWebhook(n.repositoryFullName,{url:o,secret:c,events:n.events});return e.updateWebhookState(n.id,{providerWebhookId:l.providerWebhookId,status:l.active?"healthy":"degraded",healthMessage:l.active?"Provider webhook is synchronized.":"Provider webhook exists but is inactive.",reconciled:!0})}catch(s){return e.updateWebhookState(n.id,{status:"degraded",healthMessage:s instanceof Error?s.message:"Webhook reconciliation failed",reconciled:!0})}}async function wi(e,t){let r=e.getWebhook(t),n=r?e.getConnection(r.connectionId):void 0;if(!r||!n)throw Error("Source webhook was not found");if(ya(n.provider)&&r.providerWebhookId&&!["disconnected","expired"].includes(n.status))await wo(n,e.getCredential(n.id)).deleteWebhook(r.repositoryFullName,r.providerWebhookId);return e.updateWebhookState(r.id,{status:"disabled",healthMessage:"Webhook disabled."})}var Za="1.6.0";function Gd(){let e={type:"object",required:["error"],properties:{error:{type:"object",required:["code","message","requestId"],properties:{code:{type:"string"},message:{type:"string"},requestId:{type:"string",format:"uuid"},details:{}}}}},t=(n)=>({type:"object",required:["data","page","requestId"],properties:{data:{type:"array",items:n},page:{type:"object",required:["hasMore"],properties:{nextCursor:{type:"string"},hasMore:{type:"boolean"}}},requestId:{type:"string",format:"uuid"}}}),r=(n)=>({"200":{description:"A stable cursor page.",content:{"application/json":{schema:t(n)}}},default:{$ref:"#/components/responses/Error"}});return{openapi:"3.1.0",info:{title:"ts-cloud API",version:Za,description:"Additive changes are released within v1. Breaking request or response changes require a new URL version."},servers:[{url:"/"}],security:[{bearerAuth:[]}],paths:{...Jo(),"/api/v1/projects":{get:{operationId:"listProjects",summary:"List accessible projects",parameters:[{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/Project"})}},"/api/v1/projects/{projectId}/environments":{get:{operationId:"listEnvironments",summary:"List accessible project environments",parameters:[{$ref:"#/components/parameters/ProjectId"},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/Environment"})}},"/api/v1/services":{get:{operationId:"listServices",summary:"List accessible services",parameters:[{name:"projectId",in:"query",required:!0,schema:{type:"string"}},{name:"environmentId",in:"query",schema:{type:"string"}},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/Service"})}},"/api/v1/source/connections":{get:{operationId:"listSourceConnections",summary:"List safe Git connection metadata",parameters:[{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/SourceConnection"})},post:{operationId:"createSourceConnection",summary:"Create an encrypted Git connection",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["provider","name","host"],properties:{provider:{type:"string",enum:["github","gitlab","bitbucket","gitea","generic_https","generic_ssh"]},name:{type:"string"},host:{type:"string",format:"uri"},token:{type:"string",writeOnly:!0},repositoryFullName:{type:"string"},repositoryUrl:{type:"string"}}}}}},responses:{"201":{description:"Encrypted connection created."},default:{$ref:"#/components/responses/Error"}}},delete:{operationId:"disconnectSourceConnection",summary:"Preview or safely disconnect a Git connection",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["id"],properties:{id:{type:"string"},preview:{type:"boolean"}}}}}},responses:{"200":{description:"Impact preview or disconnected connection."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/source/repositories":{get:{operationId:"listSourceRepositories",summary:"List or synchronize granted repositories",parameters:[{name:"connectionId",in:"query",required:!0,schema:{type:"string"}},{name:"sync",in:"query",schema:{type:"boolean"}},{name:"search",in:"query",schema:{type:"string"}},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/SourceRepository"})}},"/api/v1/source/refs":{get:{operationId:"listSourceRefs",summary:"List repository branches or tags",parameters:[{name:"connectionId",in:"query",required:!0,schema:{type:"string"}},{name:"repository",in:"query",required:!0,schema:{type:"string"}},{name:"repositoryId",in:"query",schema:{type:"string"}},{name:"type",in:"query",schema:{type:"string",enum:["branches","tags"]}}],responses:{"200":{description:"Provider reference page."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/source/bindings":{post:{operationId:"createSourceBinding",summary:"Bind a repository to an application",requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/SourceBindingRequest"}}}},responses:{"201":{description:"Source binding created."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/source/webhooks":{post:{operationId:"createSourceWebhook",summary:"Create and optionally reconcile a signed webhook",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["connectionId","repositoryFullName","baseUrl"],properties:{connectionId:{type:"string"},repositoryId:{type:"string"},repositoryFullName:{type:"string"},baseUrl:{type:"string",format:"uri"},events:{type:"array",items:{type:"string",enum:["push","pull_request"]}},reconcile:{type:"boolean"}}}}}},responses:{"201":{description:"Webhook endpoint created; endpoint is revealed once."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/application-detections":{post:{operationId:"detectApplication",summary:"Detect bounded application build candidates",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["files"],properties:{files:{type:"array",maxItems:1e4,items:{$ref:"#/components/schemas/DetectionFile"}}}}}}},responses:{"200":{description:"Ranked detection candidates with evidence."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/application-plans":{post:{operationId:"planApplication",summary:"Validate and normalize an application manifest",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["draft"],properties:{draft:{$ref:"#/components/schemas/ApplicationInput"},suppliedSecretNames:{type:"array",uniqueItems:!0,items:{type:"string"}}}}}}},responses:{"200":{description:"Validated plan, config patch, capabilities, costs, and missing secret names."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/application-drafts":{get:{operationId:"listApplicationDrafts",summary:"List resumable secret-free drafts",parameters:[{name:"projectId",in:"query",required:!0,schema:{type:"string"}},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/ApplicationDraft"})},post:{operationId:"createApplicationDraft",summary:"Create a resumable application draft",requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/ApplicationDraftCreateRequest"}}}},responses:{"201":{description:"Draft created."},default:{$ref:"#/components/responses/Error"}}},patch:{operationId:"updateApplicationDraft",summary:"Optimistically update a draft",requestBody:{required:!0,content:{"application/json":{schema:{allOf:[{$ref:"#/components/schemas/ApplicationDraftCreateRequest"},{type:"object",required:["id","version","step"],properties:{id:{type:"string"},version:{type:"integer",minimum:1}}}]}}}},responses:{"200":{description:"Updated draft."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/applications":{post:{operationId:"createApplication",summary:"Confirm and queue an application plan",parameters:[{name:"Idempotency-Key",in:"header",required:!0,schema:{type:"string",minLength:8,maxLength:128}}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",additionalProperties:!1,required:["draftId","version","confirmEnvironment"],properties:{draftId:{type:"string"},version:{type:"integer",minimum:1},confirmEnvironment:{type:"string",description:"Exact target environment slug."}}}}}},responses:{"202":{description:"Application operation queued; identical requests replay safely."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/application-artifacts":{post:{operationId:"uploadApplicationArtifact",summary:"Inspect and store a bounded ZIP or TAR source artifact",parameters:[{name:"X-Project-Id",in:"header",required:!0,schema:{type:"string"}},{name:"X-Artifact-Filename",in:"header",required:!0,schema:{type:"string"}}],requestBody:{required:!0,content:{"application/octet-stream":{schema:{type:"string",format:"binary",maxLength:104857600}}}},responses:{"201":{description:"Deduplicated artifact metadata; archive contents are never executed."},"413":{$ref:"#/components/responses/Error"},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/registry-connections":{get:{operationId:"listRegistryConnections",summary:"List safe private-registry metadata",parameters:[{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/RegistryConnection"})},post:{operationId:"createRegistryConnection",summary:"Create an encrypted private-registry connection",requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/RegistryConnectionRequest"}}}},responses:{"201":{description:"Encrypted registry connection created."},default:{$ref:"#/components/responses/Error"}}},patch:{operationId:"updateRegistryConnection",summary:"Test access or rotate write-only credentials",requestBody:{required:!0,content:{"application/json":{schema:{allOf:[{$ref:"#/components/schemas/RegistryConnectionRequest"},{type:"object",required:["id","action"],properties:{id:{type:"string"},action:{type:"string",enum:["test","rotate"]},image:{type:"string"}}}]}}}},responses:{"200":{description:"Safe connection health metadata."},default:{$ref:"#/components/responses/Error"}}},delete:{operationId:"disconnectRegistryConnection",summary:"Disconnect and erase registry credentials",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",additionalProperties:!1,required:["id"],properties:{id:{type:"string"}}}}}},responses:{"200":{description:"Credentials erased and connection disconnected."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/queue":{get:{operationId:"listQueue",summary:"List authorized durable operations and blocking metadata",parameters:[{name:"projectId",in:"query",schema:{type:"string"}},{name:"state",in:"query",schema:{type:"string",enum:["queued","running","succeeded","failed","cancelled","timed_out"]}},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/QueueOperation"})}},"/api/v1/preview-definitions":{get:{operationId:"listPreviewDefinitions",summary:"List preview policies",responses:r({type:"object"})},post:{operationId:"createPreviewDefinition",summary:"Configure bounded preview policy",responses:{"200":{description:"Preview definition created."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/previews":{get:{operationId:"listPreviews",summary:"List authorized persistent previews",responses:r({type:"object"})},post:{operationId:"createPreview",summary:"Create or update one immutable preview identity",responses:{"200":{description:"Preview deployment queued."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/previews/{previewId}/destroy":{post:{operationId:"destroyPreview",summary:"Confirm tagged preview teardown",responses:{"200":{description:"Teardown queued."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/previews/{previewId}/extend":{post:{operationId:"extendPreview",summary:"Extend preview TTL",responses:{"200":{description:"Expiry extended."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/previews/{previewId}/rebuild":{post:{operationId:"rebuildPreview",summary:"Rebuild the exact recorded commit",responses:{"200":{description:"Rebuild queued."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/previews/cleanup":{post:{operationId:"cleanupPreviews",summary:"Dry-run or queue TTL/keep-count teardown",responses:{"200":{description:"Cleanup plan or operations."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/compose-templates":{get:{operationId:"listComposeTemplates",summary:"List pinned verified application templates",responses:r({type:"object"})}},"/api/v1/compose-applications":{get:{operationId:"listComposeApplications",summary:"List authorized multi-service applications",responses:r({type:"object"})},post:{operationId:"createComposeApplication",summary:"Import Compose or materialize a template",responses:{"200":{description:"Editable normalized application."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/compose-applications/preview":{post:{operationId:"previewComposeApplication",summary:"Parse and diagnose Compose without mutation",responses:{"200":{description:"Normalized preview and actionable diagnostics."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/compose-applications/{applicationId}/services":{get:{operationId:"listComposeServices",summary:"Inspect per-service desired and observed state",responses:{"200":{description:"Service topology and status."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/compose-applications/{applicationId}/{action}":{post:{operationId:"operateComposeApplication",summary:"Deploy, redeploy, start, stop, scale, or delete through the durable queue",responses:{"200":{description:"Scoped operation queued."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/release-artifacts":{post:{operationId:"createReleaseArtifact",summary:"Register a verified content-addressed artifact",responses:{"200":{description:"Artifact identity registered."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/releases":{get:{operationId:"listReleases",summary:"List unified authorized release history",responses:r({type:"object"})},post:{operationId:"createRelease",summary:"Create an immutable release from an existing artifact",responses:{"200":{description:"Release record created."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/releases/capabilities":{get:{operationId:"getReleaseCapabilities",summary:"Explain supported strategies, capacity, cost, and rollback",responses:{"200":{description:"Provider-aware strategy capabilities."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/releases/{releaseId}":{get:{operationId:"getRelease",summary:"Inspect provenance, approvals, health, and transitions",responses:{"200":{description:"Release detail."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/releases/{releaseId}/{action}":{post:{operationId:"operateRelease",summary:"Promote, approve, activate, roll back, report health, or pin",responses:{"200":{description:"Release lifecycle updated."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/queue/settings":{get:{operationId:"getQueueSettings",summary:"Get effective concurrency limits",responses:{"200":{description:"Queue concurrency settings."},default:{$ref:"#/components/responses/Error"}}},patch:{operationId:"updateQueueSettings",summary:"Confirm and audit production concurrency changes",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",additionalProperties:!1,required:["confirm","concurrency"],properties:{confirm:{const:"update queue limits"},concurrency:{$ref:"#/components/schemas/QueueConcurrency"}}}}}},responses:{"200":{description:"Updated effective limits."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/queue/history":{delete:{operationId:"clearQueueHistory",summary:"Clear terminal jobs whose retention has elapsed",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",additionalProperties:!1,required:["confirm"],properties:{confirm:{const:"clear completed"},before:{type:"string",format:"date-time"},projectId:{type:"string"}}}}}},responses:{"200":{description:"Eligible history cleared with an audit event."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/operations/{operationId}/logs":{get:{operationId:"listOperationLogs",summary:"Resume ordered sanitized operation logs from a cursor",parameters:[{$ref:"#/components/parameters/OperationId"},{name:"after",in:"query",schema:{type:"integer",minimum:0}},{$ref:"#/components/parameters/Limit"}],responses:{"200":{description:"Ordered log chunks and next cursor."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/operations/{operationId}/logs/stream":{get:{operationId:"streamOperationLogs",summary:"Stream authorized operation logs with Last-Event-ID resume",parameters:[{$ref:"#/components/parameters/OperationId"},{name:"Last-Event-ID",in:"header",schema:{type:"integer",minimum:0}}],responses:{"200":{description:"Server-sent log and completion events.",content:{"text/event-stream":{schema:{type:"string"}}}},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/operations/{operationId}/cancel":{post:{operationId:"cancelOperation",summary:"Cancel queued work or request cooperative running cancellation",parameters:[{$ref:"#/components/parameters/OperationId"}],requestBody:{content:{"application/json":{schema:{type:"object"}}}},responses:{"200":{description:"Cancellation state recorded."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/operations/{operationId}/retry":{post:{operationId:"retryOperation",summary:"Retry an allow-listed failure class within the attempt limit",parameters:[{$ref:"#/components/parameters/OperationId"}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",additionalProperties:!1,required:["errorClass"],properties:{errorClass:{type:"string"},delayMs:{type:"integer",minimum:0}}}}}},responses:{"200":{description:"Retry queued."},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/deployments":{post:{operationId:"createDeployment",summary:"Queue a deployment",parameters:[{name:"Idempotency-Key",in:"header",required:!0,schema:{type:"string",minLength:8,maxLength:128}}],requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/DeploymentRequest"}}}},responses:{"202":{description:"Queued operation.",content:{"application/json":{schema:{$ref:"#/components/schemas/OperationResponse"}}}},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/operations":{get:{operationId:"listOperations",summary:"List scoped operations",parameters:[{name:"projectId",in:"query",schema:{type:"string"}},{$ref:"#/components/parameters/Limit"},{$ref:"#/components/parameters/Cursor"}],responses:r({$ref:"#/components/schemas/Operation"})}},"/api/v1/events":{get:{operationId:"listEvents",summary:"List scoped audit events",parameters:[{name:"projectId",in:"query",schema:{type:"string"}},{name:"after",in:"query",schema:{type:"integer",minimum:0}},{$ref:"#/components/parameters/Limit"}],responses:r({$ref:"#/components/schemas/Event"})}},"/api/v1/events/stream":{get:{operationId:"streamEvents",summary:"Stream scoped audit events",responses:{"200":{description:"Authenticated server-sent event stream.",content:{"text/event-stream":{schema:{type:"string"}}}},default:{$ref:"#/components/responses/Error"}}}},"/api/v1/openapi.json":{get:{operationId:"getOpenApi",summary:"Get the OpenAPI contract",security:[],responses:{"200":{description:"OpenAPI 3.1 contract."}}}}},components:{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer",bearerFormat:"tsc_v1"}},parameters:{Limit:{name:"limit",in:"query",schema:{type:"integer",minimum:1,maximum:100,default:50}},Cursor:{name:"cursor",in:"query",schema:{type:"string"}},ProjectId:{name:"projectId",in:"path",required:!0,schema:{type:"string"}},OperationId:{name:"operationId",in:"path",required:!0,schema:{type:"string"}}},responses:{Error:{description:"Stable error envelope.",content:{"application/json":{schema:e}}}},schemas:{Project:{type:"object",required:["id","slug","name"],properties:{id:{type:"string"},slug:{type:"string"},name:{type:"string"},description:{type:"string"}}},Environment:{type:"object",required:["id","projectId","slug","name","kind"],properties:{id:{type:"string"},projectId:{type:"string"},slug:{type:"string"},name:{type:"string"},kind:{type:"string"},region:{type:"string"}}},Service:{type:"object",required:["id","projectId","kind","slug","name"],properties:{id:{type:"string"},projectId:{type:"string"},environmentId:{type:"string"},kind:{type:"string"},slug:{type:"string"},name:{type:"string"},metadata:{type:"object",additionalProperties:!0}}},SourceConnection:{type:"object",required:["id","provider","name","host","status","credentialConfigured"],properties:{id:{type:"string"},provider:{type:"string"},name:{type:"string"},host:{type:"string"},status:{type:"string"},credentialConfigured:{type:"boolean"},credentialFingerprint:{type:"string"},grantedScopes:{type:"array",items:{type:"string"}}}},SourceRepository:{type:"object",required:["id","connectionId","fullName","cloneUrl","defaultBranch"],properties:{id:{type:"string"},connectionId:{type:"string"},fullName:{type:"string"},cloneUrl:{type:"string"},defaultBranch:{type:"string"},visibility:{type:"string"},archived:{type:"boolean"}}},SourceBindingRequest:{type:"object",additionalProperties:!1,required:["projectId","connectionId","repositoryFullName"],properties:{projectId:{type:"string"},environmentId:{type:"string"},resourceId:{type:"string"},connectionId:{type:"string"},repositoryId:{type:"string"},repositoryFullName:{type:"string"},defaultBranch:{type:"string"},branchRule:{type:"string"},tagRule:{type:"string"},monorepoRoot:{type:"string"},includePaths:{type:"array",items:{type:"string"}},excludePaths:{type:"array",items:{type:"string"}},submodules:{type:"boolean"},cloneDepth:{type:"integer",minimum:1},deployKeyId:{type:"string"},autoDeploy:{type:"boolean"},pullRequestPreviews:{type:"boolean"}}},DetectionFile:{type:"object",additionalProperties:!1,required:["path"],properties:{path:{type:"string"},size:{type:"integer",minimum:0},content:{type:"string",maxLength:262144}}},ApplicationInput:{type:"object",additionalProperties:!1,required:["schemaVersion","name","slug","projectId","environmentId","source","build","runtime"],properties:{schemaVersion:{const:1},name:{type:"string"},slug:{type:"string"},projectId:{type:"string"},environmentId:{type:"string"},source:{type:"object",required:["kind"],properties:{kind:{type:"string",enum:["git","local","artifact","image"]}},additionalProperties:!0},build:{type:"object",required:["kind"],properties:{kind:{type:"string",enum:["dockerfile","buildpack","static","server","serverless","prebuilt_image"]},secretNames:{type:"array",uniqueItems:!0,items:{type:"string"}}},additionalProperties:!0},runtime:{type:"object",required:["architecture","target"],properties:{architecture:{type:"string",enum:["x86_64","arm64"]},target:{type:"string",enum:["server","serverless","container"]},port:{type:"integer",minimum:1,maximum:65535},healthCheck:{type:"object",additionalProperties:!0}},additionalProperties:!0},environment:{type:"object",additionalProperties:{oneOf:[{type:"string"},{type:"object",additionalProperties:!1,required:["secretRef"],properties:{secretRef:{type:"string"}}}]}},requiredSecretNames:{type:"array",uniqueItems:!0,items:{type:"string"}},domain:{type:"object",properties:{hostname:{type:"string"},path:{type:"string"},tls:{type:"boolean"}}}}},ApplicationDraftCreateRequest:{type:"object",additionalProperties:!1,required:["projectId","draft"],properties:{projectId:{type:"string"},name:{type:"string"},draft:{$ref:"#/components/schemas/ApplicationInput"},step:{type:"string",enum:["source","build","runtime","environment","domain","review"]},suppliedSecretNames:{type:"array",uniqueItems:!0,description:"Names only; values must use the secrets boundary.",items:{type:"string"}}}},ApplicationDraft:{type:"object",required:["id","projectId","input","step","status","version"],properties:{id:{type:"string"},projectId:{type:"string"},input:{$ref:"#/components/schemas/ApplicationInput"},step:{type:"string"},suppliedSecretNames:{type:"array",items:{type:"string"}},status:{type:"string",enum:["draft","ready","applied"]},version:{type:"integer"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},RegistryConnectionRequest:{type:"object",properties:{provider:{type:"string",enum:["docker_hub","ghcr","ecr","gcr","generic"]},name:{type:"string"},host:{type:"string"},username:{type:"string",writeOnly:!0},password:{type:"string",writeOnly:!0},token:{type:"string",writeOnly:!0},credentialExpiresAt:{type:"string",format:"date-time"},expiresAt:{type:"string",format:"date-time"}}},RegistryConnection:{type:"object",required:["id","provider","name","host","credentialConfigured","status","version"],properties:{id:{type:"string"},provider:{type:"string"},name:{type:"string"},host:{type:"string"},credentialConfigured:{type:"boolean"},credentialFingerprint:{type:"string"},credentialExpiresAt:{type:"string",format:"date-time"},status:{type:"string",enum:["pending","healthy","degraded","expired","disconnected"]},healthMessage:{type:"string"},lastTestedAt:{type:"string",format:"date-time"},version:{type:"integer"}}},QueueConcurrency:{type:"object",additionalProperties:!1,properties:{project:{type:"integer",minimum:1,maximum:100},environment:{type:"integer",minimum:1,maximum:100},provider:{type:"integer",minimum:1,maximum:100},builds:{type:"integer",minimum:1,maximum:100}}},QueueOperation:{allOf:[{$ref:"#/components/schemas/Operation"},{type:"object",required:["queue"],properties:{queue:{type:"object",required:["maxAttempts","availableAt","timeoutSeconds","retryClasses","resumePolicy","cancellationMode","retentionUntil"],properties:{lockKey:{type:"string"},providerKey:{type:"string"},buildSlot:{type:"boolean"},maxAttempts:{type:"integer"},availableAt:{type:"string",format:"date-time"},timeoutSeconds:{type:"integer"},heartbeatAt:{type:"string",format:"date-time"},currentStep:{type:"string"},blockedReason:{type:"string"},retryClasses:{type:"array",items:{type:"string"}},resumePolicy:{type:"string",enum:["fail","requeue"]},cancellationMode:{type:"string",enum:["cooperative","provider_non_cancellable"]},retentionUntil:{type:"string",format:"date-time"}}},approximatePosition:{type:"object",properties:{ahead:{type:"integer"},precision:{const:"bounded"}}}}}]},DeploymentRequest:{type:"object",additionalProperties:!1,required:["projectId","environmentId"],properties:{projectId:{type:"string"},environmentId:{type:"string"},serviceId:{type:"string"},action:{type:"string",enum:["deploy","rollback"],default:"deploy"},revision:{type:"string"}}},Operation:{type:"object",required:["id","state","kind","correlationId","createdAt"],properties:{id:{type:"string"},state:{type:"string"},kind:{type:"string"},correlationId:{type:"string"},createdAt:{type:"string",format:"date-time"}}},OperationResponse:{type:"object",required:["operation","idempotentReplay","requestId"],properties:{operation:{$ref:"#/components/schemas/Operation"},idempotentReplay:{type:"boolean"},requestId:{type:"string",format:"uuid"}}},Event:{type:"object",required:["id","sequence","type","level","correlationId","createdAt"],properties:{id:{type:"string"},sequence:{type:"integer"},type:{type:"string"},level:{type:"string"},correlationId:{type:"string"},payload:{},createdAt:{type:"string",format:"date-time"}}}}}}}function bS(e){return Buffer.from(JSON.stringify(e)).toString("base64url")}function SS(e){if(!e)return;try{let t=JSON.parse(Buffer.from(e,"base64url").toString("utf8"));return t&&typeof t==="object"&&!Array.isArray(t)?t:void 0}catch{return}}function on(e,t,r,n=["createdAt","id"]){let i=Math.min(100,Math.max(1,Number(t.searchParams.get("limit"))||50)),o=SS(t.searchParams.get("cursor"));if(t.searchParams.has("cursor")&&!o)throw new p("invalid_cursor","The pagination cursor is invalid.",400);let s=0;if(o){let m=e.findIndex((E)=>n.every((k)=>E[k]===o[k]));if(m<0)throw new p("invalid_cursor","The pagination cursor is no longer available.",400);s=m+1}let c=e.slice(s,s+i),l=s+i<e.length,a=c.at(-1);return{data:c,page:{hasMore:l,nextCursor:l&&a?bS(Object.fromEntries(n.map((m)=>[m,a[m]]))):void 0},requestId:r}}function Kd(e){let t=new $i(e.controlPlane,e.identities),r=new b(e.controlPlane),n=new Fe(e.controlPlane),i=new Be(e.controlPlane),o=new et(e.controlPlane),s=e.spend?.store??new ir(e.controlPlane,{now:e.now}),c={store:s,service:e.spend?.service??new st(s)},l=new Map,a=e.now??(()=>new Date),m=e.rateLimit??120,E=(O,q,G,Y={})=>new Response(JSON.stringify(O),{status:q,headers:{"content-type":"application/json; charset=utf-8","cache-control":"no-store","x-request-id":G,"x-api-version":Za,...Y}}),k=(O,q,G,Y,re,he)=>E({error:{code:O,message:q,requestId:Y,details:re}},G,Y,he);return async(O,q)=>{let G=new URL(O.url);if(!G.pathname.startsWith("/api/v1"))return;let Y=crypto.randomUUID();if(G.pathname==="/api/v1/openapi.json"&&O.method==="GET")return E(Gd(),200,Y,{"cache-control":"public, max-age=300"});let re=O.headers.get("authorization")??"",he=re.startsWith("Bearer ")?re.slice(7).trim():"",ee=he?e.identities.verifyToken(he,q):void 0;if(!ee)return k("unauthorized","A valid bearer token is required.",401,Y,void 0,{"www-authenticate":'Bearer realm="ts-cloud", error="invalid_token"'});let Re=l.get(ee.token.id),at=a().getTime(),ze=!Re||at-Re.start>=60000?{start:at,count:0}:Re;ze.count+=1,l.set(ee.token.id,ze);let Vt=Math.max(0,m-ze.count),ut={"x-ratelimit-limit":String(m),"x-ratelimit-remaining":String(Vt),"x-ratelimit-reset":String(Math.ceil((ze.start+60000)/1000))};if(ze.count>m)return k("rate_limited","API rate limit exceeded.",429,Y,void 0,{...ut,"retry-after":String(Math.max(1,Math.ceil((ze.start+60000-at)/1000)))});try{let Te,Qe=async()=>{let J=await O.text();if(J.length>1048576)throw new p("payload_too_large","Request body exceeds 1 MB.",413);try{return JSON.parse(J)}catch{throw new p("invalid_json","Request body must be valid JSON.",400)}},Tt=/^\/api\/v1\/projects\/([^/]+)\/environments$/.exec(G.pathname),ki=/^\/api\/v1\/operations\/([^/]+)\/logs(?:\/(stream))?$/.exec(G.pathname),po=/^\/api\/v1\/operations\/([^/]+)\/(cancel|retry)$/.exec(G.pathname),gi=/^\/api\/v1\/previews\/([^/]+)\/(destroy|extend|rebuild)$/.exec(G.pathname),Ri=/^\/api\/v1\/compose-applications\/([^/]+)\/(deploy|redeploy|start|stop|scale|delete)$/.exec(G.pathname),Pi=/^\/api\/v1\/compose-applications\/([^/]+)\/services$/.exec(G.pathname),xi=/^\/api\/v1\/releases\/([^/]+)\/(promote|approve|activate|rollback|health|pin)$/.exec(G.pathname);if(O.method==="GET"&&G.pathname==="/api/v1/projects")Te=on(t.listProjects(ee),G,Y);else if(O.method==="GET"&&Tt)Te=on(t.listEnvironments(ee,decodeURIComponent(Tt[1])),G,Y);else if(O.method==="GET"&&G.pathname==="/api/v1/services"){let J=G.searchParams.get("projectId");if(!J)throw new p("validation_error","projectId is required.",422);Te=on(t.listServices(ee,J,G.searchParams.get("environmentId")??void 0),G,Y)}else if(O.method==="GET"&&G.pathname==="/api/v1/operations")Te=on(t.listOperations(ee,G.searchParams.get("projectId")??void 0),G,Y);else if(O.method==="GET"&&G.pathname==="/api/v1/previews"){let J=G.searchParams.get("projectId")??void 0,pe=n.previews.listInstances({projectId:J}).filter((Ie)=>{try{return t.authorize(ee,"deployments:read",{type:"resource",id:Ie.resourceId}),!0}catch{return!1}}).map((Ie)=>({...Ie}));Te=on(pe,G,Y)}else if(O.method==="GET"&&G.pathname==="/api/v1/compose-templates")Te=on(er().map((J)=>({...J})),G,Y,["id","version"]);else if(O.method==="GET"&&G.pathname==="/api/v1/releases/capabilities"){let J=String(G.searchParams.get("kind")??"");Te={capabilities:Qt({kind:J,hasHealthGate:G.searchParams.get("health")==="true",replicas:Number(G.searchParams.get("replicas"))||1}),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/releases"){let J=G.searchParams.get("projectId");if(!J)throw new p("validation_error","projectId is required.",422);t.authorize(ee,"project:read",{type:"project",id:J});let pe=o.releases.list({projectId:J,environmentId:G.searchParams.get("environmentId")??void 0,resourceId:G.searchParams.get("resourceId")??void 0}).filter((Ie)=>{try{return t.authorize(ee,"deployments:read",{type:"resource",id:Ie.resourceId}),!0}catch{return!1}}).map((Ie)=>({...Ie,artifact:o.releases.getArtifact(Ie.artifactId),transitions:o.releases.transitions(Ie.id),approvals:o.releases.approvals(Ie.id)}));Te=on(pe,G,Y)}else if(O.method==="POST"&&G.pathname==="/api/v1/release-artifacts"){let J=await Qe();t.authorize(ee,"applications:manage",{type:"organization"}),Te={artifact:o.releases.registerArtifact({organizationId:ee.serviceAccount.organizationId,digest:String(J.digest??""),kind:String(J.kind??""),uri:String(J.uri??""),size:Number(J.size),mediaType:typeof J.mediaType==="string"?J.mediaType:void 0,provenance:J.provenance,attestation:J.attestation}),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/releases"){let J=await Qe(),pe=String(J.resourceId??"");t.authorize(ee,"applications:manage",{type:"resource",id:pe}),Te={release:o.releases.create({organizationId:ee.serviceAccount.organizationId,projectId:String(J.projectId??""),environmentId:String(J.environmentId??""),resourceId:pe,artifactId:String(J.artifactId??""),kind:String(J.kind??""),sourceSha:typeof J.sourceSha==="string"?J.sourceSha:void 0,config:J.config??{},manifest:J.manifest??{},provenance:J.provenance,strategy:String(J.strategy??"atomic"),healthGate:J.healthGate,hooks:J.hooks,drainSeconds:Number(J.drainSeconds)||void 0,graceSeconds:Number(J.graceSeconds)||void 0,automaticRollback:J.automaticRollback!==!1,actorId:ee.actor.id,trigger:typeof J.trigger==="string"?J.trigger:"api",approvalRequired:J.approvalRequired===!0,replicas:Number(J.replicas)||void 0}),requestId:Y}}else if(O.method==="GET"&&/^\/api\/v1\/releases\/[^/]+$/.test(G.pathname)){let J=decodeURIComponent(G.pathname.split("/").at(-1)),pe=o.releases.get(J);if(!pe)throw new p("not_found","Release was not found.",404);t.authorize(ee,"deployments:read",{type:"resource",id:pe.resourceId}),Te={release:pe,artifact:o.releases.getArtifact(pe.artifactId),transitions:o.releases.transitions(J),approvals:o.releases.approvals(J),requestId:Y}}else if(O.method==="POST"&&xi){let J=o.releases.get(decodeURIComponent(xi[1]));if(!J)throw new p("not_found","Release was not found.",404);let pe=await Qe(),Ie=xi[2];if(Ie==="promote"){let ke=String(pe.targetResourceId??"");t.authorize(ee,"deployments:create",{type:"resource",id:ke}),Te={release:o.releases.promote(J.id,{targetEnvironmentId:String(pe.targetEnvironmentId??""),targetResourceId:ke,config:pe.config??{},strategy:pe.strategy,healthGate:pe.healthGate,actorId:ee.actor.id,approvalRequired:pe.approvalRequired===!0}),requestId:Y}}else if(Ie==="approve")t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={release:o.releases.approve(J.id,{actorId:ee.actor.id,decision:pe.decision==="rejected"?"rejected":"approved",comment:typeof pe.comment==="string"?pe.comment:void 0}),requestId:Y};else if(Ie==="activate")t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={operation:t.operation(o.enqueueActivation(J,{actorId:ee.actor.id})),requestId:Y};else if(Ie==="rollback")t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={operation:t.operation(o.enqueueRollback(J,{actorId:ee.actor.id,targetReleaseId:typeof pe.targetReleaseId==="string"?pe.targetReleaseId:void 0})),requestId:Y};else if(Ie==="health"){t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId});let ke=o.completeHealthGate(J.id,{healthy:pe.healthy===!0,operationId:typeof pe.operationId==="string"?pe.operationId:void 0,health:pe.health,message:typeof pe.message==="string"?pe.message:void 0});Te={release:ke.release,rollbackOperation:ke.rollbackOperation?t.operation(ke.rollbackOperation):void 0,requestId:Y}}else t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={release:o.releases.pin(J.id,pe.pinned!==!1,typeof pe.reason==="string"?pe.reason:void 0),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/compose-applications"){let J=G.searchParams.get("projectId");if(!J)throw new p("validation_error","projectId is required.",422);t.authorize(ee,"project:read",{type:"project",id:J});let pe=i.applications.list({projectId:J,environmentId:G.searchParams.get("environmentId")??void 0}).filter((Ie)=>{try{return t.authorize(ee,"deployments:read",{type:"resource",id:Ie.resourceId}),!0}catch{return!1}}).map((Ie)=>({...Ie,services:i.applications.services(Ie.id)}));Te=on(pe,G,Y)}else if(O.method==="POST"&&G.pathname==="/api/v1/compose-applications/preview"){let J=await Qe(),pe=String(J.projectId??"");t.authorize(ee,"project:read",{type:"project",id:pe}),Te={result:i.applications.preview(String(J.source??""),{name:String(J.name??""),slug:typeof J.slug==="string"?J.slug:void 0,projectId:pe,environmentId:String(J.environmentId??"")}),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/compose-applications"){let J=await Qe(),pe=String(J.projectId??"");t.authorize(ee,"applications:manage",{type:"environment",id:String(J.environmentId??"")});let Ie={name:String(J.name??""),slug:typeof J.slug==="string"?J.slug:void 0,projectId:pe,environmentId:String(J.environmentId??""),createdByActorId:ee.actor.id},ke=typeof J.templateId==="string"?i.applications.fromTemplate(J.templateId,J.inputs&&typeof J.inputs==="object"&&!Array.isArray(J.inputs)?J.inputs:{},{...Ie,version:typeof J.templateVersion==="string"?J.templateVersion:void 0}):i.applications.import(String(J.source??""),Ie);Te={application:ke.application,diagnostics:ke.parsed.diagnostics,requestId:Y}}else if(O.method==="GET"&&Pi){let J=i.applications.get(decodeURIComponent(Pi[1]));if(!J)throw new p("not_found","Compose application was not found.",404);t.authorize(ee,"deployments:read",{type:"resource",id:J.resourceId}),Te={application:J,services:i.applications.services(J.id),requestId:Y}}else if(O.method==="POST"&&Ri){let J=i.applications.get(decodeURIComponent(Ri[1]));if(!J)throw new p("not_found","Compose application was not found.",404);let pe=Ri[2],Ie=await Qe();t.authorize(ee,pe==="delete"||pe==="stop"?"deployments:cancel":"deployments:create",{type:"resource",id:J.resourceId}),Te={operation:t.operation(i.enqueue(J,pe,{actorId:ee.actor.id,service:typeof Ie.service==="string"?Ie.service:void 0,replicas:Number.isFinite(Number(Ie.replicas))?Number(Ie.replicas):void 0,removeVolumes:Ie.removeVolumes===!0,confirmation:typeof Ie.confirm==="string"?Ie.confirm:void 0})),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/preview-definitions"){let J=G.searchParams.get("projectId");if(!J)throw new p("validation_error","projectId is required.",422);t.authorize(ee,"project:read",{type:"project",id:J}),Te=on(n.previews.listDefinitions(J).map((pe)=>({...pe})),G,Y)}else if(O.method==="POST"&&G.pathname==="/api/v1/preview-definitions"){let J=await Qe();t.authorize(ee,"config:write",{type:"resource",id:String(J.resourceId??"")}),Te={definition:n.previews.createDefinition({...J,projectId:String(J.projectId??""),resourceId:String(J.resourceId??""),baseEnvironmentId:String(J.baseEnvironmentId??""),domainPattern:String(J.domainPattern??""),createdByActorId:ee.actor.id}),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/previews"){let J=await Qe(),pe=n.previews.getDefinition(String(J.definitionId??""));if(!pe)throw new p("not_found","Preview definition was not found.",404);t.authorize(ee,"deployments:create",{type:"resource",id:pe.resourceId});let Ie=n.previews.upsert({definitionId:pe.id,sourceProvider:"api",repository:typeof J.repository==="string"?J.repository:"api",branch:String(J.branch??""),pullRequestNumber:Number(J.pullRequestNumber)||void 0,fork:J.fork===!0,commitSha:String(J.commitSha??""),createdByActorId:ee.actor.id});Te={preview:Ie.preview,operation:t.operation(n.enqueueDeploy(Ie.preview,{created:Ie.created,actorId:ee.actor.id})),requestId:Y}}else if(O.method==="POST"&&gi){let J=n.previews.getInstance(decodeURIComponent(gi[1]));if(!J)throw new p("not_found","Preview was not found.",404);let pe=await Qe(),Ie=gi[2];if(Ie==="destroy"){if(t.authorize(ee,"deployments:cancel",{type:"resource",id:J.resourceId}),pe.confirm!==J.name)throw new p("confirmation_required",`Type ${J.name} to confirm preview teardown.`,409);Te={operation:t.operation(n.enqueueDestroy(J,"api",ee.actor.id)),requestId:Y}}else if(Ie==="extend")t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={preview:n.previews.extend(J.id,Number(pe.hours)),requestId:Y};else t.authorize(ee,"deployments:create",{type:"resource",id:J.resourceId}),Te={operation:t.operation(n.enqueueDeploy(J,{actorId:ee.actor.id,reason:"manual_rebuild"})),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/previews/cleanup"){t.authorize(ee,"automation:manage",{type:"organization"});let J=await Qe();if(!J.dryRun&&J.confirm!=="cleanup previews")throw new p("confirmation_required","Type cleanup previews to confirm preview cleanup.",409);Te={...n.cleanup({dryRun:J.dryRun===!0,maxAgeHours:Number(J.maxAgeHours)||void 0,keepCount:Number(J.keepCount)||void 0,actorId:ee.actor.id}),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/queue"){let J=G.searchParams.get("projectId")??void 0,pe=G.searchParams.get("state"),Ie=r.list({projectId:J,state:["queued","running","succeeded","failed","cancelled","timed_out"].includes(pe)?pe:void 0,limit:500}).filter((ke)=>{let Dt=ke.operation.resourceId?{type:"resource",id:ke.operation.resourceId}:ke.operation.environmentId?{type:"environment",id:ke.operation.environmentId}:ke.operation.projectId?{type:"project",id:ke.operation.projectId}:{type:"organization"};try{return t.authorize(ee,"deployments:read",Dt),!0}catch{return!1}}).map((ke)=>({...t.operation(ke.operation),queue:ke.job,approximatePosition:ke.approximatePosition}));Te=on(Ie,G,Y)}else if(O.method==="GET"&&G.pathname==="/api/v1/queue/settings")t.authorize(ee,"deployments:read",ee.token.scope),Te={concurrency:r.limits,requestId:Y};else if(O.method==="PATCH"&&G.pathname==="/api/v1/queue/settings"){t.authorize(ee,"automation:manage",{type:"organization"});let J=await Qe();if(J.confirm!=="update queue limits")throw new p("confirmation_required","Type update queue limits to confirm production concurrency changes.",409);Te={concurrency:r.configureConcurrency(J.concurrency??{},{organizationId:ee.serviceAccount.organizationId,actorId:ee.actor.id}),requestId:Y}}else if(O.method==="DELETE"&&G.pathname==="/api/v1/queue/history"){t.authorize(ee,"automation:manage",{type:"organization"});let J=await Qe();if(J.confirm!=="clear completed")throw new p("confirmation_required","Type clear completed to confirm queue retention cleanup.",409);Te={deleted:r.clearCompleted({before:typeof J.before==="string"?J.before:void 0,actorId:ee.actor.id,projectId:typeof J.projectId==="string"?J.projectId:void 0}),requestId:Y}}else if(O.method==="GET"&&ki){let J=e.controlPlane.getOperation(decodeURIComponent(ki[1]));if(!J)throw new p("not_found","Operation was not found.",404);let pe=J.resourceId?{type:"resource",id:J.resourceId}:J.environmentId?{type:"environment",id:J.environmentId}:J.projectId?{type:"project",id:J.projectId}:{type:"organization"};t.authorize(ee,"deployments:read",pe);let Ie=O.headers.get("last-event-id")?.trim(),ke=Number(Ie||G.searchParams.get("after")||0);if(ki[2]==="stream"){let rr=new TextEncoder,ve=ke,pt,ct=!1,Je=new ReadableStream({start(Jr){let vs=()=>{if(ct)return;if(!e.identities.verifyToken(he,q)){if(ct=!0,pt)clearInterval(pt);Jr.close();return}let Di=r.logs(J.id,{after:ve,limit:500});for(let Ot of Di)ve=Ot.sequence,Jr.enqueue(rr.encode(`id: ${Ot.sequence}
|
|
8
|
+
event: log
|
|
9
|
+
data: ${JSON.stringify(Ot)}
|
|
10
|
+
|
|
11
|
+
`));let kt=e.controlPlane.getOperation(J.id);if(kt&&["succeeded","failed","cancelled","timed_out"].includes(kt.state)&&!r.logs(J.id,{after:ve,limit:1}).length){if(ct=!0,pt)clearInterval(pt);Jr.enqueue(rr.encode(`event: complete
|
|
12
|
+
data: ${JSON.stringify({state:kt.state,cursor:ve})}
|
|
13
|
+
|
|
14
|
+
`)),Jr.close()}};if(vs(),!ct)pt=setInterval(vs,500);O.signal.addEventListener("abort",()=>{if(ct=!0,pt)clearInterval(pt);try{Jr.close()}catch{}},{once:!0})},cancel(){if(ct=!0,pt)clearInterval(pt)}});return new Response(Je,{headers:{"content-type":"text/event-stream","cache-control":"no-store","x-accel-buffering":"no","x-request-id":Y,...ut}})}let Dt=r.logs(J.id,{after:ke,limit:Number(G.searchParams.get("limit"))||void 0});Te={data:Dt,cursor:Dt.at(-1)?.sequence??ke,hasMore:Dt.length>=Math.min(1000,Math.max(1,Number(G.searchParams.get("limit"))||200)),requestId:Y}}else if(O.method==="POST"&&po){let J=e.controlPlane.getOperation(decodeURIComponent(po[1]));if(!J)throw new p("not_found","Operation was not found.",404);let pe=J.resourceId?{type:"resource",id:J.resourceId}:J.environmentId?{type:"environment",id:J.environmentId}:J.projectId?{type:"project",id:J.projectId}:{type:"organization"},Ie=await Qe();if(po[2]==="cancel")t.authorize(ee,"deployments:cancel",pe),Te={operation:t.operation(r.requestCancellation(J.id,ee.actor.id)),requestId:Y};else t.authorize(ee,"deployments:create",pe),Te={operation:t.operation(r.retry(J.id,String(Ie.errorClass??"manual"),{delayMs:Number(Ie.delayMs)||0,actorId:ee.actor.id})),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/source/connections"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:read",ee.token.scope),Te=on(e.sources.listConnections(ee.serviceAccount.organizationId),G,Y,["createdAt","id"])}else if(O.method==="GET"&&G.pathname==="/api/v1/source/repositories"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:read",ee.token.scope);let J=e.sources.getConnection(G.searchParams.get("connectionId")??"");if(!J||J.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Source connection was not found.",404);if(G.searchParams.get("sync")==="true")t.authorize(ee,"sources:manage",{type:"organization"}),await Pr(e.sources,J.id,{search:G.searchParams.get("search")??void 0});Te=on(e.sources.listRepositories(J.id,G.searchParams.get("search")??void 0),G,Y,["fullName","id"])}else if(O.method==="GET"&&G.pathname==="/api/v1/source/refs"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:read",ee.token.scope);let J=G.searchParams.get("connectionId")??"",pe=e.sources.getConnection(J);if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Source connection was not found.",404);Te=await Kt(e.sources,{connectionId:J,repository:G.searchParams.get("repository")??"",repositoryId:G.searchParams.get("repositoryId")??void 0,type:G.searchParams.get("type")==="tags"?"tags":"branches",cursor:G.searchParams.get("cursor")??void 0,deployKeyId:G.searchParams.get("deployKeyId")??void 0})}else if(O.method==="POST"&&G.pathname==="/api/v1/application-detections"){t.authorize(ee,"applications:manage",ee.token.scope);let J=await Qe();if(!Array.isArray(J.files)||J.files.length>1e4)throw new p("validation_error","files must contain at most 10,000 entries.",422);Te={candidates:At(J.files.map((pe)=>({path:String(pe.path??""),size:Number(pe.size??0),content:typeof pe.content==="string"?pe.content.slice(0,262144):void 0}))),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/application-plans"){t.authorize(ee,"applications:manage",ee.token.scope);let J=await Qe();Te={plan:se(J.draft,Array.isArray(J.suppliedSecretNames)?J.suppliedSecretNames.map(String):[]),requestId:Y}}else if(O.method==="GET"&&G.pathname==="/api/v1/application-drafts"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);let J=G.searchParams.get("projectId")??"";t.authorize(ee,"applications:read",{type:"project",id:J}),Te=on(e.applications.drafts.list(J),G,Y,["updatedAt","id"])}else if(O.method==="POST"&&G.pathname==="/api/v1/application-drafts"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);let J=await Qe(),pe=String(J.projectId??J.draft?.projectId??"");t.authorize(ee,"applications:manage",{type:"project",id:pe});let Ie=e.controlPlane.getProject(pe);if(!Ie||Ie.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Project was not found.",404);let ke=e.applications.drafts.create({organizationId:Ie.organizationId,projectId:pe,name:String(J.name??J.draft?.name??"Application draft"),draft:{...J.draft,projectId:pe},step:J.step,suppliedSecretNames:Array.isArray(J.suppliedSecretNames)?J.suppliedSecretNames.map(String):[],actorId:ee.actor.id});return E({draft:ke,requestId:Y},201,Y,ut)}else if(O.method==="PATCH"&&G.pathname==="/api/v1/application-drafts"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);let J=await Qe(),pe=e.applications.drafts.get(String(J.id??""));if(!pe)throw new p("not_found","Application draft was not found.",404);t.authorize(ee,"applications:manage",{type:"project",id:pe.projectId}),Te={draft:e.applications.drafts.update(pe.id,Number(J.version),{draft:{...J.draft,projectId:pe.projectId},step:J.step,suppliedSecretNames:Array.isArray(J.suppliedSecretNames)?J.suppliedSecretNames.map(String):void 0,actorId:ee.actor.id}),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/applications"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);let J=O.headers.get("idempotency-key")??"";if(!J)throw new p("idempotency_required","Idempotency-Key is required for application creation.",428);if(!/^[A-Za-z0-9._:-]{8,128}$/.test(J))throw new p("validation_error","Idempotency-Key must contain 8-128 safe characters.",422);let pe=await Qe(),Ie=e.applications.drafts.get(String(pe.draftId??""));if(!Ie)throw new p("not_found","Application draft was not found.",404);t.authorize(ee,"applications:manage",{type:"project",id:Ie.projectId});let ke=yS("sha256").update(`POST
|
|
15
|
+
/api/v1/applications
|
|
16
|
+
${JSON.stringify(pe)}`).digest("hex"),Dt=e.identities.getIdempotency(ee.token.id,J);if(Dt){if(Dt.requestHash!==ke)throw new p("idempotency_conflict","Idempotency-Key was already used for another request.",409);let ve=Dt.operationId?e.controlPlane.getOperation(Dt.operationId):void 0,pt=ve?.resourceId?e.controlPlane.getResource(ve.resourceId):void 0;if(!ve||!pt)throw new p("idempotency_unavailable","The original application operation is no longer available.",409);return E({resource:pt,operation:t.operation(ve),plan:se(Ie.input,Ie.suppliedSecretNames),idempotentReplay:!0,requestId:Y},202,Y,{...ut,"idempotent-replayed":"true"})}let rr=Nr({controlPlane:e.controlPlane,drafts:e.applications.drafts,draftId:Ie.id,expectedVersion:Number(pe.version),confirmEnvironment:String(pe.confirmEnvironment??""),actorId:ee.actor.id});return e.identities.saveIdempotency({tokenId:ee.token.id,key:J,requestHash:ke,operationId:rr.operation.id,responseStatus:202,responseBody:{draftId:Ie.id}}),E({resource:rr.resource,operation:t.operation(rr.operation),plan:rr.plan,idempotentReplay:!1,requestId:Y},202,Y,ut)}else if(O.method==="GET"&&G.pathname==="/api/v1/registry-connections"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);t.authorize(ee,"applications:read",ee.token.scope),Te=on(e.applications.registries.list(ee.serviceAccount.organizationId),G,Y,["createdAt","id"])}else if(O.method==="POST"&&G.pathname==="/api/v1/registry-connections"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);t.authorize(ee,"applications:manage",{type:"organization"});let J=await Qe(),pe=e.applications.registries.create({organizationId:ee.serviceAccount.organizationId,provider:J.provider,name:String(J.name??"Container registry"),host:String(J.host??""),credential:J.token||J.password?{username:typeof J.username==="string"?J.username:void 0,password:typeof J.password==="string"?J.password:void 0,token:typeof J.token==="string"?J.token:void 0}:void 0,credentialExpiresAt:typeof J.credentialExpiresAt==="string"?J.credentialExpiresAt:void 0,actorId:ee.actor.id});return E({registry:pe,requestId:Y},201,Y,ut)}else if(O.method==="PATCH"&&G.pathname==="/api/v1/registry-connections"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);t.authorize(ee,"applications:manage",{type:"organization"});let J=await Qe(),pe=e.applications.registries.get(String(J.id??""));if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Registry connection was not found.",404);if(J.action==="test")Te={registry:await e.applications.registries.test(pe.id,{image:typeof J.image==="string"?J.image:void 0}),requestId:Y};else if(J.action==="rotate")Te={registry:e.applications.registries.rotate(pe.id,{username:J.username,password:J.password,token:J.token},{expiresAt:J.expiresAt,actorId:ee.actor.id}),requestId:Y};else throw new p("validation_error","action must be test or rotate.",422)}else if(O.method==="DELETE"&&G.pathname==="/api/v1/registry-connections"){if(!e.applications)throw new p("not_found","Application onboarding is unavailable.",404);t.authorize(ee,"applications:manage",{type:"organization"});let J=await Qe(),pe=e.applications.registries.get(String(J.id??""));if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Registry connection was not found.",404);Te={registry:e.applications.registries.disconnect(pe.id,ee.actor.id),requestId:Y}}else if(O.method==="POST"&&G.pathname==="/api/v1/application-artifacts"){if(!e.applications?.artifacts)throw new p("not_found","Application artifact storage is unavailable.",404);let J=O.headers.get("x-project-id")??"";t.authorize(ee,"applications:manage",{type:"project",id:J});let pe=e.controlPlane.getProject(J);if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Project was not found.",404);if(Number(O.headers.get("content-length")??0)>104857600)throw new p("payload_too_large","Artifact exceeds 100 MB.",413);let ke=e.applications.artifacts.create({organizationId:pe.organizationId,projectId:J,filename:O.headers.get("x-artifact-filename")??"application.zip",bytes:new Uint8Array(await O.arrayBuffer()),actorId:ee.actor.id});return E({artifact:ke,requestId:Y},201,Y,ut)}else if(O.method==="POST"&&G.pathname==="/api/v1/source/connections"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:manage",{type:"organization"});let J=await Qe(),pe=String(J.provider??"");if(!["github","gitlab","bitbucket","gitea","generic_https","generic_ssh"].includes(pe))throw new p("validation_error","A supported provider is required.",422);let Ie=pe==="github"&&(J.privateKey||J.appId)?{appId:typeof J.appId==="string"?J.appId:void 0,installationId:typeof J.installationId==="string"?J.installationId:void 0,privateKey:typeof J.privateKey==="string"?J.privateKey:void 0}:pe!=="generic_ssh"&&J.token?{token:String(J.token),username:typeof J.username==="string"?J.username:void 0}:void 0,ke,Dt,rr;return e.controlPlane.database.transaction(()=>{if(ke=e.sources.createConnection({organizationId:ee.serviceAccount.organizationId,provider:pe,name:String(J.name??pe),host:String(J.host??""),owner:typeof J.owner==="string"?J.owner:void 0,authKind:J.authKind,credential:Ie,createdByActorId:ee.actor.id}),typeof J.repositoryUrl==="string"&&typeof J.repositoryFullName==="string")Dt=e.sources.upsertRepository({connectionId:ke.id,providerRepositoryId:`manual:${J.repositoryFullName}`,fullName:J.repositoryFullName,cloneUrl:J.repositoryUrl,defaultBranch:String(J.defaultBranch??"main"),visibility:"unknown",archived:!1,metadata:{source:"api"}});if(pe==="generic_ssh")rr=e.sources.createDeployKey({connectionId:ke.id,name:String(J.deployKeyName??"Repository deploy key"),publicKey:String(J.publicKey??""),privateKey:String(J.deployPrivateKey??""),host:String(J.sshHost??""),hostKey:String(J.hostKey??""),actorId:ee.actor.id})})(),E({connection:ke,repository:Dt,deployKey:rr,requestId:Y},201,Y,ut)}else if(O.method==="POST"&&G.pathname==="/api/v1/source/bindings"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);let J=await Qe(),pe=String(J.projectId??"");t.authorize(ee,"sources:manage",{type:"project",id:pe});let Ie=e.sources.getConnection(String(J.connectionId??""));if(!Ie||Ie.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Source connection was not found.",404);let ke=e.sources.createBinding({projectId:pe,environmentId:typeof J.environmentId==="string"?J.environmentId:void 0,resourceId:typeof J.resourceId==="string"?J.resourceId:void 0,connectionId:Ie.id,repositoryId:typeof J.repositoryId==="string"?J.repositoryId:void 0,repositoryFullName:String(J.repositoryFullName??""),defaultBranch:String(J.defaultBranch??"main"),branchRule:typeof J.branchRule==="string"?J.branchRule:void 0,tagRule:typeof J.tagRule==="string"?J.tagRule:void 0,monorepoRoot:String(J.monorepoRoot??"."),includePaths:Array.isArray(J.includePaths)?J.includePaths.map(String):[],excludePaths:Array.isArray(J.excludePaths)?J.excludePaths.map(String):[],submodules:J.submodules===!0,cloneDepth:typeof J.cloneDepth==="number"?J.cloneDepth:void 0,deployKeyId:typeof J.deployKeyId==="string"&&J.deployKeyId?J.deployKeyId:void 0,autoDeploy:J.autoDeploy!==!1,pullRequestPreviews:J.pullRequestPreviews!==!1,actorId:ee.actor.id});return E({binding:ke,requestId:Y},201,Y,ut)}else if(O.method==="POST"&&G.pathname==="/api/v1/source/webhooks"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:manage",{type:"organization"});let J=await Qe(),pe=e.sources.getConnection(String(J.connectionId??""));if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Source connection was not found.",404);let Ie=typeof J.baseUrl==="string"?J.baseUrl:void 0;if(!Ie)throw new p("validation_error","baseUrl is required.",422);let ke=e.sources.createWebhook({connectionId:pe.id,repositoryId:typeof J.repositoryId==="string"?J.repositoryId:void 0,repositoryFullName:String(J.repositoryFullName??""),events:Array.isArray(J.events)?J.events.map(String):void 0}),Dt=Ct(Ie,ke.webhook),rr=J.reconcile===!1?ke.webhook:await Jt(e.sources,ke.webhook.id,Ie);return E({webhook:rr,endpoint:Dt,endpointRevealOnce:!0,requestId:Y},201,Y,ut)}else if(O.method==="DELETE"&&G.pathname==="/api/v1/source/connections"){if(!e.sources)throw new p("not_found","Source integrations are unavailable.",404);t.authorize(ee,"sources:manage",{type:"organization"});let J=await Qe(),pe=e.sources.getConnection(String(J.id??""));if(!pe||pe.organizationId!==ee.serviceAccount.organizationId)throw new p("not_found","Source connection was not found.",404);let Ie=e.sources.listBindings({connectionId:pe.id,status:"active"});if(J.preview===!0)return E({preview:!0,affectedBindings:Ie,requestId:Y},200,Y,ut);return E({...e.sources.disconnectConnection(pe.id,ee.actor.id),requestId:Y},200,Y,ut)}else if(O.method==="GET"&&(G.pathname==="/api/v1/events"||G.pathname==="/api/v1/events/stream")){let J=t.listEvents(ee,G.searchParams.get("projectId")??void 0,Number(G.searchParams.get("after"))||void 0);if(G.pathname.endsWith("/stream")){let pe=new TextEncoder,Ie=J.reduce((ve,pt)=>Math.max(ve,Number(pt.sequence)),Number(G.searchParams.get("after"))||0),ke,Dt=!1,rr=new ReadableStream({start(ve){let pt=(ct)=>ve.enqueue(pe.encode(`id: ${ct.sequence}
|
|
17
|
+
event: ${ct.type}
|
|
18
|
+
data: ${JSON.stringify(ct)}
|
|
19
|
+
|
|
20
|
+
`));if(J.length)J.forEach(pt);else ve.enqueue(pe.encode(`: connected
|
|
21
|
+
|
|
22
|
+
`));ke=setInterval(()=>{if(Dt)return;let ct=e.identities.verifyToken(he,q);if(!ct){if(Dt=!0,ke)clearInterval(ke);ve.close();return}try{let Je=t.listEvents(ct,G.searchParams.get("projectId")??void 0,Ie);for(let Jr of Je)pt(Jr),Ie=Math.max(Ie,Number(Jr.sequence));if(!Je.length)ve.enqueue(pe.encode(`: heartbeat ${Date.now()}
|
|
23
|
+
|
|
24
|
+
`))}catch{if(Dt=!0,ke)clearInterval(ke);ve.close()}},1000),O.signal.addEventListener("abort",()=>{if(Dt=!0,ke)clearInterval(ke);try{ve.close()}catch{}},{once:!0})},cancel(){if(Dt=!0,ke)clearInterval(ke)}});return new Response(rr,{status:200,headers:{"content-type":"text/event-stream","cache-control":"no-store",connection:"keep-alive","x-accel-buffering":"no","x-request-id":Y,...ut}})}Te=on(J,G,Y,["sequence","id"])}else if(O.method==="POST"&&G.pathname==="/api/v1/deployments"){let J=O.headers.get("idempotency-key")??"";if(!J)throw new p("idempotency_required","Idempotency-Key is required for deployment requests.",428);let pe=await O.text();if(pe.length>1048576)throw new p("payload_too_large","Request body exceeds 1 MB.",413);let Ie;try{Ie=JSON.parse(pe)}catch{throw new p("invalid_json","Request body must be valid JSON.",400)}if(!Ie||typeof Ie.projectId!=="string"||typeof Ie.environmentId!=="string"||Ie.action!==void 0&&!["deploy","rollback"].includes(Ie.action))throw new p("validation_error","projectId, environmentId, and a valid action are required.",422);let ke=t.createDeployment(ee,Ie,J);return E({operation:ke.operation,idempotentReplay:ke.replay,requestId:Y},202,Y,{...ut,...ke.replay?{"idempotent-replayed":"true"}:{}})}else{let J=await Ko({...c,authorization:t,now:a},ee,{method:O.method,url:G,body:Qe});if(J===void 0)throw new p("not_found","API resource was not found.",404);Te=J}return E(Te,200,Y,ut)}catch(Te){if(Te instanceof p)return k(Te.code,Te.message,Te.status,Y,Te.details,ut);if(G.pathname.startsWith("/api/v1/source/")||G.pathname.startsWith("/api/v1/application")||G.pathname.startsWith("/api/v1/compose-")||G.pathname==="/api/v1/registry-connections")return k("validation_error",Te instanceof Error?Te.message:"Integration request could not be completed.",422,Y,void 0,ut);return k("internal_error","The API request could not be completed.",500,Y,void 0,ut)}}}import{createCipheriv as IS,createDecipheriv as CS,createHash as bg,randomBytes as Wi}from"node:crypto";import{createHmac as vS,timingSafeEqual as wS}from"node:crypto";var Qd="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function ec(e){let t=0,r=0,n="";for(let i of e){r=r<<8|i,t+=8;while(t>=5)n+=Qd[r>>>t-5&31],t-=5}if(t>0)n+=Qd[r<<5-t&31];return n}function pg(e){let t=e.toUpperCase().replace(/[^A-Z2-7]/g,""),r=0,n=0,i=[];for(let o of t){let s=Qd.indexOf(o);if(s<0)throw Error("Invalid base32 secret");if(n=n<<5|s,r+=5,r>=8)i.push(n>>>r-8&255),r-=8}return Buffer.from(i)}function gg(e,t,r=6){let n=Buffer.alloc(8);n.writeBigUInt64BE(BigInt(t));let i=vS("sha1",pg(e)).update(n).digest(),o=i[i.length-1]&15,s=(i[o]&127)<<24|(i[o+1]&255)<<16|(i[o+2]&255)<<8|i[o+3]&255;return String(s%10**r).padStart(r,"0")}function tc(e,t,r=Date.now(),n=1){let i=t.replace(/[\s-]/g,"");if(!/^\d{6}$/.test(i))return;let o=Buffer.from(i),s=Math.floor(r/1000/30);for(let c=-n;c<=n;c++){if(s+c<0)continue;let l=Buffer.from(gg(e,s+c));if(o.length===l.length&&wS(o,l))return s+c}return}function Yd(e){let t=e.issuer?.trim()||"ts-cloud",r=`${t}:${e.account}`;return`otpauth://totp/${encodeURIComponent(r)}?secret=${encodeURIComponent(e.secret)}&issuer=${encodeURIComponent(t)}&algorithm=SHA1&digits=6&period=30`}var Sg=1800000,Co=43200000,vg=3600000,wg=300000,Ig=600000;function Yn(e){return typeof e==="string"?e:void 0}function Cg(e){if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}}function ES(e){let t=e.trim();if(!/^[a-z0-9][a-z0-9._-]{1,31}$/i.test(t))throw Error("Username must be 2-32 characters: letters, numbers, dot, dash or underscore");return t}function Xd(e){if(e===void 0||!e.trim())return;let t=e.trim().toLowerCase();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)||t.length>254)throw Error("A valid email address is required");return t}function TS(e){let t=e.trim().toLowerCase();if(!/^[a-z0-9][a-z0-9-]{1,47}$/.test(t))throw Error("OIDC provider slug must be 2-48 lowercase letters, numbers or dashes");return t}function AS(e){let t=new URL(e.trim());if(t.search||t.hash||t.username||t.password)throw Error("OIDC issuer cannot contain credentials, a query, or a fragment");if(t.protocol!=="https:"&&!(t.protocol==="http:"&&["127.0.0.1","::1","localhost"].includes(t.hostname)))throw Error("OIDC issuer must use HTTPS");return t.href.replace(/\/$/,"")}function kS(e){let t=[...new Set(e.map((r)=>r.trim().toLowerCase()).filter(Boolean))];if(t.length===0)throw Error("At least one explicit OIDC email domain is required");if(t.some((r)=>!/^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/.test(r)||!r.includes(".")||r.includes("..")))throw Error("OIDC email domains must be explicit DNS names without wildcards");return t}function RS(e){let t=[...new Set(["openid",...e??["email","profile"]].map((r)=>r.trim()).filter(Boolean))];if(t.some((r)=>!/^[\x21\x23-\x5B\x5D-\x7E]+$/.test(r)))throw Error("OIDC scopes contain unsupported characters");return t}function mi(e){return bg("sha256").update(e).digest("hex")}function ba(e){return{id:String(e.id),actorId:String(e.actor_id),username:String(e.username),email:Yn(e.email),emailVerifiedAt:Yn(e.email_verified_at),passwordHash:String(e.password_hash),credentialVersion:Number(e.credential_version),requiresPasswordUpgrade:Number(e.requires_password_upgrade)===1,disabledAt:Yn(e.disabled_at),lastLoginAt:Yn(e.last_login_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function mg(e,t){let r=Yn(e.consumed_at),n=String(e.expires_at);return{id:String(e.id),identityId:String(e.identity_id),type:String(e.type),metadata:Cg(e.metadata),expiresAt:n,consumedAt:r,createdAt:String(e.created_at),state:r?"consumed":n<=t?"expired":"pending"}}function Zd(e,t){let r=Yn(e.revoked_at),n=String(e.idle_expires_at),i=String(e.absolute_expires_at);return{id:String(e.id),identityId:String(e.identity_id),credentialVersion:Number(e.credential_version),authMethod:String(e.auth_method),userAgent:Yn(e.user_agent),networkHint:Yn(e.network_hint),createdAt:String(e.created_at),lastUsedAt:String(e.last_used_at),idleExpiresAt:n,absoluteExpiresAt:i,recentAuthAt:String(e.recent_auth_at),mfaAt:Yn(e.mfa_at),revokedAt:r,state:r?"revoked":n<=t||i<=t?"expired":"active"}}function fg(e){let t=Yn(e.verified_at),r=Yn(e.disabled_at);return{id:String(e.id),identityId:String(e.identity_id),type:"totp",label:String(e.label),createdAt:String(e.created_at),verifiedAt:t,disabledAt:r,state:r?"disabled":t?"active":"pending"}}function eu(e,t){let r=Yn(e.consumed_at),n=String(e.expires_at),i=Number(e.attempts);return{id:String(e.id),identityId:String(e.identity_id),purpose:String(e.purpose),attempts:i,expiresAt:n,consumedAt:r,createdAt:String(e.created_at),state:r?"consumed":i>=5?"locked":n<=t?"expired":"pending"}}function hg(e){let t=Cg(e);return Array.isArray(t)?t.filter((r)=>typeof r==="string"):[]}function rc(e){return{id:String(e.id),organizationId:String(e.organization_id),slug:String(e.slug),name:String(e.name),issuer:String(e.issuer),clientId:String(e.client_id),hasClientSecret:typeof e.client_secret_ciphertext==="string"&&e.client_secret_ciphertext.length>0,scopes:hg(e.scopes),allowedDomains:hg(e.allowed_domains),defaultRole:String(e.default_role),enabled:Number(e.enabled)===1,enforceSso:Number(e.enforce_sso)===1,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function yg(e,t){let r=Yn(e.consumed_at),n=String(e.expires_at);return{id:String(e.id),providerId:String(e.provider_id),redirectUri:String(e.redirect_uri),returnPath:String(e.return_path),expiresAt:n,consumedAt:r,createdAt:String(e.created_at),state:r?"consumed":n<=t?"expired":"pending"}}function PS(e){return{id:String(e.id),providerId:String(e.provider_id),identityId:String(e.identity_id),subject:String(e.subject),email:String(e.email),linkedAt:String(e.linked_at),lastLoginAt:String(e.last_login_at)}}class De{controlPlane;nowFn;idFn;encryptionKey;constructor(e,t={}){this.controlPlane=e;this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID()),this.encryptionKey=t.encryptionKey?bg("sha256").update(t.encryptionKey).digest():void 0}now(){return this.nowFn().toISOString()}run(e,t){this.controlPlane.database.run(e,t)}encrypt(e){if(!this.encryptionKey)throw Error("Authentication encryption key is not configured");let t=Wi(12),r=IS("aes-256-gcm",this.encryptionKey,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.encryptionKey)throw Error("Authentication encryption key is not configured");let[t,r,n,i]=e.split(".");if(t!=="v1"||!r||!n||!i)throw Error("Encrypted authentication value is unavailable");let o=CS("aes-256-gcm",this.encryptionKey,Buffer.from(r,"base64url"));return o.setAuthTag(Buffer.from(n,"base64url")),Buffer.concat([o.update(Buffer.from(i,"base64url")),o.final()]).toString("utf8")}createIdentity(e){if(!this.controlPlane.getActor(e.actorId))throw Error("Authentication actor was not found");let t=ES(e.username),r=Xd(e.email),n=e.id??this.idFn(),i=this.now();return this.run(`INSERT INTO auth_identities (id, actor_id, username, email, email_verified_at, password_hash, requires_password_upgrade, created_at, updated_at)
|
|
25
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n,e.actorId,t,r??null,e.emailVerified&&r?i:null,e.passwordHash,e.requiresPasswordUpgrade?1:0,i,i]),this.getIdentity(n)}getIdentity(e){let t=this.controlPlane.database.query("SELECT * FROM auth_identities WHERE id = ?").get(e);return t?ba(t):void 0}getIdentityByActor(e){let t=this.controlPlane.database.query("SELECT * FROM auth_identities WHERE actor_id = ?").get(e);return t?ba(t):void 0}getIdentityByUsername(e){let t=this.controlPlane.database.query("SELECT * FROM auth_identities WHERE username = ? COLLATE NOCASE").get(e.trim());return t?ba(t):void 0}getIdentityByEmail(e){let t=this.controlPlane.database.query("SELECT * FROM auth_identities WHERE email = ? COLLATE NOCASE").get(e.trim().toLowerCase());return t?ba(t):void 0}listIdentities(){return this.controlPlane.database.query("SELECT * FROM auth_identities ORDER BY username COLLATE NOCASE").all().map(ba)}updatePassword(e,t,r={}){if(!this.getIdentity(e))throw Error("Authentication identity was not found");let i=this.now();return this.controlPlane.transaction(()=>{if(this.run(`UPDATE auth_identities SET password_hash = ?, credential_version = credential_version + 1,
|
|
26
|
+
requires_password_upgrade = ?, updated_at = ? WHERE id = ?`,[t,r.requiresUpgrade?1:0,i,e]),r.revokeSessions!==!1)this.run("UPDATE auth_sessions SET revoked_at = ? WHERE identity_id = ? AND revoked_at IS NULL",[i,e])}),this.getIdentity(e)}rehashPassword(e,t){let r=this.now();this.run("UPDATE auth_identities SET password_hash = ?, requires_password_upgrade = 0, updated_at = ? WHERE id = ?",[t,r,e]);let n=this.getIdentity(e);if(!n)throw Error("Authentication identity was not found");return n}setVerifiedEmail(e,t){let r=Xd(t),n=this.now();this.run("UPDATE auth_identities SET email = ?, email_verified_at = ?, updated_at = ? WHERE id = ?",[r,n,n,e]);let i=this.getIdentity(e);if(!i)throw Error("Authentication identity was not found");return i}recordLogin(e){let t=this.now();this.run("UPDATE auth_identities SET last_login_at = ?, updated_at = ? WHERE id = ?",[t,t,e]);let r=this.getIdentity(e);if(!r)throw Error("Authentication identity was not found");return r}setDisabled(e,t){let r=this.now();this.controlPlane.transaction(()=>{if(this.run("UPDATE auth_identities SET disabled_at = ?, credential_version = credential_version + 1, updated_at = ? WHERE id = ?",[t?r:null,r,e]),t)this.run("UPDATE auth_sessions SET revoked_at = ? WHERE identity_id = ? AND revoked_at IS NULL",[r,e])});let n=this.getIdentity(e);if(!n)throw Error("Authentication identity was not found");return n}createActionToken(e,t,r={}){if(!this.getIdentity(e))throw Error("Authentication identity was not found");let n=Wi(32).toString("base64url"),i=this.idFn(),o=this.now(),s=new Date(this.nowFn().getTime()+Math.min(86400000,Math.max(60000,r.ttlMs??vg))).toISOString();return this.run("INSERT INTO auth_action_tokens (id, identity_id, type, token_hash, metadata, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[i,e,t,mi(n),JSON.stringify(r.metadata??{}),s,o]),{actionToken:this.getActionToken(i),token:n}}getActionToken(e){let t=this.controlPlane.database.query("SELECT * FROM auth_action_tokens WHERE id = ?").get(e);return t?mg(t,this.now()):void 0}consumeActionToken(e,t){return this.controlPlane.transaction(()=>{let r=this.controlPlane.database.query("SELECT * FROM auth_action_tokens WHERE token_hash = ? AND type = ?").get(mi(e),t);if(!r)throw Error("Action token is invalid");let n=mg(r,this.now());if(n.state!=="pending")throw Error(`Action token is ${n.state}`);if(this.controlPlane.database.run("UPDATE auth_action_tokens SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL AND expires_at > ?",[this.now(),n.id,this.now()]).changes!==1)throw Error("Action token is no longer available");return this.getActionToken(n.id)})}revokeActionTokens(e,t){return this.controlPlane.database.run("UPDATE auth_action_tokens SET consumed_at = ? WHERE identity_id = ? AND type = ? AND consumed_at IS NULL",[this.now(),e,t]).changes}createSession(e){let t=this.getIdentity(e.identityId);if(!t||t.disabledAt)throw Error("Authentication identity is unavailable");let r=this.idFn(),n=Wi(32).toString("base64url"),i=`v2.${r}.${n}`,o=this.now(),s=Math.min(86400000,Math.max(60000,e.idleTtlMs??Sg)),c=Math.min(2592000000,Math.max(s,e.absoluteTtlMs??Co));return this.run(`INSERT INTO auth_sessions (id, identity_id, token_hash, credential_version, auth_method, user_agent, network_hint,
|
|
27
|
+
created_at, last_used_at, idle_expires_at, absolute_expires_at, recent_auth_at, mfa_at)
|
|
28
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r,t.id,mi(i),t.credentialVersion,e.authMethod??"local",e.userAgent?.slice(0,256)??null,e.networkHint?.slice(0,128)??null,o,o,new Date(this.nowFn().getTime()+s).toISOString(),new Date(this.nowFn().getTime()+c).toISOString(),e.recentAuthAt??o,e.mfaAt??null]),{session:this.getSession(r),token:i}}getSession(e){let t=this.controlPlane.database.query("SELECT * FROM auth_sessions WHERE id = ?").get(e);return t?Zd(t,this.now()):void 0}verifySessionToken(e){let t=/^v2\.([^.]+)\.[A-Za-z0-9_-]{40,}$/.exec(e);if(!t)return;let r=this.controlPlane.database.query("SELECT * FROM auth_sessions WHERE id = ? AND token_hash = ?").get(t[1],mi(e));if(!r)return;let n=Zd(r,this.now()),i=this.getIdentity(n.identityId);if(!i||i.disabledAt||n.state!=="active"||n.credentialVersion!==i.credentialVersion)return;let o=this.now(),s=new Date(r.idle_expires_at).getTime()-new Date(r.last_used_at).getTime();return this.run("UPDATE auth_sessions SET last_used_at = ?, idle_expires_at = ? WHERE id = ?",[o,new Date(Math.min(this.nowFn().getTime()+s,new Date(n.absoluteExpiresAt).getTime())).toISOString(),n.id]),{identity:i,session:this.getSession(n.id)}}listSessions(e,t={}){let r=this.controlPlane.database.query("SELECT * FROM auth_sessions WHERE identity_id = ? ORDER BY last_used_at DESC").all(e).map((n)=>Zd(n,this.now()));return t.includeInactive?r:r.filter((n)=>n.state==="active")}revokeSession(e,t){return this.controlPlane.database.run("UPDATE auth_sessions SET revoked_at = ? WHERE id = ? AND identity_id = ? AND revoked_at IS NULL",[this.now(),t,e]).changes===1}revokeOtherSessions(e,t){return this.controlPlane.database.run("UPDATE auth_sessions SET revoked_at = ? WHERE identity_id = ? AND id != ? AND revoked_at IS NULL",[this.now(),e,t]).changes}getMfaFactor(e){let t=this.controlPlane.database.query("SELECT * FROM auth_mfa_factors WHERE identity_id = ?").get(e);return t?fg(t):void 0}beginTotpEnrollment(e,t={}){let r=this.getIdentity(e);if(!r)throw Error("Authentication identity was not found");let n=this.getMfaFactor(e);if(n?.state==="active")throw Error("MFA is already enabled");let i=ec(Wi(20)),o=t.label?.trim().slice(0,80)||r.email||r.username,s=n?.id??this.idFn(),c=this.now();return this.controlPlane.transaction(()=>{if(n)this.run("UPDATE auth_mfa_factors SET label = ?, secret_ciphertext = ?, created_at = ?, verified_at = NULL, disabled_at = NULL WHERE id = ?",[o,this.encrypt(i),c,s]);else this.run("INSERT INTO auth_mfa_factors (id, identity_id, label, secret_ciphertext, created_at) VALUES (?, ?, ?, ?, ?)",[s,e,o,this.encrypt(i),c]);this.run("DELETE FROM auth_recovery_codes WHERE identity_id = ?",[e])}),{factor:this.getMfaFactor(e),secret:i,uri:Yd({secret:i,account:o,issuer:t.issuer})}}verifyTotpEnrollment(e,t){let r=this.controlPlane.database.query("SELECT * FROM auth_mfa_factors WHERE identity_id = ?").get(e);if(!r||fg(r).state!=="pending")throw Error("MFA enrollment is not pending");let n=tc(this.decrypt(String(r.secret_ciphertext)),t,this.nowFn().getTime());if(n===void 0)throw Error("Authenticator code is invalid");let i=Array.from({length:10},()=>{let s=ec(Wi(8)).slice(0,12);return`${s.slice(0,4)}-${s.slice(4,8)}-${s.slice(8)}`}),o=this.now();return this.controlPlane.transaction(()=>{this.run("UPDATE auth_mfa_factors SET verified_at = ?, disabled_at = NULL, last_used_step = ? WHERE identity_id = ?",[o,n,e]),this.run("DELETE FROM auth_recovery_codes WHERE identity_id = ?",[e]);for(let s of i)this.run("INSERT INTO auth_recovery_codes (id, identity_id, code_hash, created_at) VALUES (?, ?, ?, ?)",[this.idFn(),e,mi(`${e}:${s.replace(/-/g,"").toUpperCase()}`),o])}),{factor:this.getMfaFactor(e),recoveryCodes:i}}verifyMfaCode(e,t,r={}){let n=this.controlPlane.database.query("SELECT * FROM auth_mfa_factors WHERE identity_id = ? AND verified_at IS NOT NULL AND disabled_at IS NULL").get(e);if(!n)return{valid:!1};let i=tc(this.decrypt(String(n.secret_ciphertext)),t,this.nowFn().getTime());if(i!==void 0){if(this.controlPlane.database.run("UPDATE auth_mfa_factors SET last_used_step = ? WHERE identity_id = ? AND (last_used_step IS NULL OR last_used_step < ?)",[i,e,i]).changes===1)return{valid:!0,method:"totp"}}let o=t.replace(/[-\s]/g,"").toUpperCase();if(!/^[A-Z2-7]{12}$/.test(o))return{valid:!1};let s=mi(`${e}:${o}`),c=this.controlPlane.database.query("SELECT * FROM auth_recovery_codes WHERE identity_id = ? AND code_hash = ? AND consumed_at IS NULL").get(e,s);if(!c)return{valid:!1};if(r.consumeRecovery!==!1){if(this.controlPlane.database.run("UPDATE auth_recovery_codes SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL",[this.now(),String(c.id)]).changes!==1)return{valid:!1}}return{valid:!0,method:"recovery"}}remainingRecoveryCodes(e){return Number(this.controlPlane.database.query("SELECT COUNT(*) AS count FROM auth_recovery_codes WHERE identity_id = ? AND consumed_at IS NULL").get(e)?.count??0)}disableMfa(e){let t=this.now();this.controlPlane.transaction(()=>{this.run("UPDATE auth_mfa_factors SET disabled_at = ? WHERE identity_id = ? AND disabled_at IS NULL",[t,e]),this.run("DELETE FROM auth_recovery_codes WHERE identity_id = ?",[e]),this.run("UPDATE auth_mfa_challenges SET consumed_at = ? WHERE identity_id = ? AND consumed_at IS NULL",[t,e])})}createMfaChallenge(e,t){if(this.getMfaFactor(e)?.state!=="active")throw Error("MFA is not enabled");let r=Wi(32).toString("base64url"),n=this.idFn(),i=this.now(),o=new Date(this.nowFn().getTime()+wg).toISOString();return this.controlPlane.transaction(()=>{this.run("UPDATE auth_mfa_challenges SET consumed_at = ? WHERE identity_id = ? AND purpose = ? AND consumed_at IS NULL",[i,e,t]),this.run("INSERT INTO auth_mfa_challenges (id, identity_id, purpose, token_hash, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?)",[n,e,t,mi(r),o,i])}),{challenge:this.getMfaChallenge(n),token:r}}getMfaChallenge(e){let t=this.controlPlane.database.query("SELECT * FROM auth_mfa_challenges WHERE id = ?").get(e);return t?eu(t,this.now()):void 0}inspectMfaChallengeToken(e,t){let r=this.controlPlane.database.query("SELECT * FROM auth_mfa_challenges WHERE token_hash = ? AND purpose = ?").get(mi(e),t);return r?eu(r,this.now()):void 0}completeMfaChallenge(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM auth_mfa_challenges WHERE token_hash = ? AND purpose = ?").get(mi(e),r);if(!n)throw Error("MFA challenge is invalid");let i=eu(n,this.now());if(i.state!=="pending")throw Error(`MFA challenge is ${i.state}`);let o=this.verifyMfaCode(i.identityId,t);if(!o.valid||!o.method)throw this.run("UPDATE auth_mfa_challenges SET attempts = attempts + 1 WHERE id = ?",[i.id]),Error("Authenticator or recovery code is invalid");if(this.controlPlane.database.run("UPDATE auth_mfa_challenges SET consumed_at = ? WHERE id = ? AND consumed_at IS NULL AND attempts < 5 AND expires_at > ?",[this.now(),i.id,this.now()]).changes!==1)throw Error("MFA challenge is no longer available");return{identity:this.getIdentity(i.identityId),challenge:this.getMfaChallenge(i.id),method:o.method}}markSessionStepUp(e,t=!1){let r=this.now();this.run("UPDATE auth_sessions SET recent_auth_at = ?, mfa_at = CASE WHEN ? = 1 THEN ? ELSE mfa_at END WHERE id = ? AND revoked_at IS NULL",[r,t?1:0,r,e]);let n=this.getSession(e);if(!n)throw Error("Authentication session was not found");return n}isRecentlyAuthenticated(e,t=600000){return this.nowFn().getTime()-new Date(e.recentAuthAt).getTime()<=t}upsertOidcProvider(e){if(!this.controlPlane.getOrganization(e.organizationId))throw Error("OIDC provider organization was not found");let t=TS(e.slug),r=e.name.trim().slice(0,80);if(!r)throw Error("OIDC provider name is required");let n=AS(e.issuer),i=e.clientId.trim();if(!i||i.length>512)throw Error("OIDC client ID is required");let o=RS(e.scopes),s=kS(e.allowedDomains),c=e.id?this.getOidcProvider(e.id):this.getOidcProviderBySlug(t),l=this.now();if(c){if(c.organizationId!==e.organizationId)throw Error("OIDC provider belongs to another organization");return this.run(`UPDATE auth_oidc_providers SET slug = ?, name = ?, issuer = ?, client_id = ?,
|
|
29
|
+
client_secret_ciphertext = COALESCE(?, client_secret_ciphertext), scopes = ?, allowed_domains = ?,
|
|
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
|
+
client_secret_ciphertext, scopes, allowed_domains, default_role, enabled, enforce_sso, created_at, updated_at)
|
|
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?rc(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?rc(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(rc).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:rc(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()+Ig).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,mi(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?yg(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,mi(t));if(!r)throw Error("OIDC transaction is invalid");let n=yg(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?PS(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=Xd(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 Sa(e,t){let r=e.notifications?.email?.from;if(!r)return!1;try{let{EmailClient:n}=await import("./chunk-yn34zgr2.js");return await new n({region:e.project.region,defaultFrom:r}).send(t),!0}catch{return!1}}import{randomBytes as xS}from"node:crypto";import{chmodSync as DS,existsSync as OS,mkdirSync as _S,readFileSync as NS,writeFileSync as $S}from"node:fs";import{dirname as MS}from"node:path";function D(e){let t=process.env.TS_CLOUD_AUTH_ENCRYPTION_KEY?.trim();if(t)return t;let r=A(e,"auth-encryption-key");try{if(OS(r)){let i=NS(r,"utf8").trim();if(i)return i}}catch{}let n=xS(32).toString("base64url");try{_S(MS(r),{recursive:!0,mode:448}),$S(r,`${n}
|
|
34
|
+
`,{mode:384}),DS(r,384)}catch{}return n}import{constants as LS,createHash as tu,createPublicKey as BS,createVerify as jS,timingSafeEqual as FS}from"node:crypto";var Tg=new Set(["RS256","PS256","ES256"]),Eg=60;function nc(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 ru(e,t){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`${t} is invalid`);return e}async function nu(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 ru(JSON.parse(i),t)}catch(o){if(o instanceof Error&&o.message===`${t} is invalid`)throw o;throw Error(`${t} returned invalid JSON`)}}function US(e,t){let r=tu("sha256").update(e).digest(),n=tu("sha256").update(t).digest();return FS(r,n)}function Ag(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 cn(e,t=fetch){let r=nc(e.issuer,"OIDC issuer"),n=new URL(`${r.pathname.replace(/\/$/,"")}/.well-known/openid-configuration`,r.origin),i=await nu(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}`);nc(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)=>Tg.has(s)))throw Error("OIDC provider does not offer a supported ID-token signing algorithm");return i}async function iu(e,t,r,n,i=fetch){let o=e.getOidcProviderBySlug(t);if(!o?.enabled)throw Error("OIDC provider is unavailable");let s=nc(r,"Application origin").origin,c=await cn(o,i),l=`${s}/auth/oidc/${encodeURIComponent(o.slug)}/callback`,a=e.beginOidcTransaction(o.id,l,Ag(n)),m=new URL(c.authorization_endpoint);return m.searchParams.set("response_type","code"),m.searchParams.set("client_id",o.clientId),m.searchParams.set("redirect_uri",l),m.searchParams.set("scope",o.scopes.join(" ")),m.searchParams.set("state",a.state),m.searchParams.set("nonce",a.nonce),m.searchParams.set("code_challenge",tu("sha256").update(a.verifier).digest("base64url")),m.searchParams.set("code_challenge_method","S256"),{authorizationUrl:m.href,expiresAt:a.transaction.expiresAt}}function zS(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:ru(JSON.parse(Buffer.from(t[0],"base64url").toString("utf8")),"OIDC ID-token header"),claims:ru(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 VS(e,t,r){let n=zS(e),i=typeof n.header.alg==="string"?n.header.alg:"",o=typeof n.header.kid==="string"?n.header.kid:"";if(!Tg.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 nu(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 k=E;return k.kid===o&&(!k.alg||k.alg===i)&&(!k.use||k.use==="sig")});if(!c)throw Error("OIDC ID-token signing key was not found");let l=BS({key:c,format:"jwk"}),a=jS("SHA256").update(n.signingInput).end();if(!(i==="PS256"?a.verify({key:l,padding:LS.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 qS(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-Eg)throw Error("OIDC ID token is expired");if(typeof e.iat!=="number"||e.iat>o+Eg)throw Error("OIDC ID-token issued-at time is invalid");if(typeof e.nonce!=="string"||!US(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 ou(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=nc(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 cn(n,r),a=new URLSearchParams({grant_type:"authorization_code",code:t.code,redirect_uri:o.transaction.redirectUri,code_verifier:o.verifier}),m={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 q=(Y)=>new URLSearchParams({value:Y}).toString().slice(6),G=`${q(n.clientId)}:${q(c)}`;m.authorization=`Basic ${Buffer.from(G).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 k=await nu(await r(l.token_endpoint,{method:"POST",headers:m,body:a,redirect:"error",signal:AbortSignal.timeout(1e4)}),"OIDC token exchange");if(typeof k.id_token!=="string")throw Error("OIDC token response did not include an ID token");let O=await VS(k.id_token,l,r);return{identity:qS(O,n,o.nonce,t.now??new Date),returnPath:o.transaction.returnPath}}import{createHash as JS,randomBytes as WS}from"node:crypto";var Rg=new Set(ie),Pg=7776000000,xg=31536000000,Dg=86400000;function Hi(e){return typeof e==="string"?e:void 0}function kg(e){return JS("sha256").update(e).digest("hex")}function HS(e){try{let t=JSON.parse(String(e));return Array.isArray(t)?t.filter((r)=>typeof r==="string"&&Rg.has(r)):[]}catch{return[]}}function GS(e){let t=String(e.scope_type);return t==="organization"?{type:t}:{type:t,id:String(e.scope_id)}}function su(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 au(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:HS(e.capabilities),scope:GS(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 KS(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 Ue{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
|
+
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?su(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?su(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(su).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((k)=>!Rg.has(k)))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 k of n)if(!Z({membership:r,grants:this.controlPlane.listGrants(r.id),capability:k,target:o}).allowed)throw Error(`Service-account membership does not grant ${k} at the token scope`);let s=e.expiresAt?new Date(e.expiresAt):new Date(this.nowFn().getTime()+Pg);if(!Number.isFinite(s.getTime())||s.getTime()<=this.nowFn().getTime()+60000||s.getTime()>this.nowFn().getTime()+xg)throw Error("API token expiry must be between one minute and one year from now");let c=this.idFn(),l=WS(32).toString("base64url"),a=`tsc_v1.${c}.${l}`,m=`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
|
+
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",kg(a),m,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:m,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?au(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)=>au(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],kg(e));if(!n)return;let i=au(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?KS(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()+Dg).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)
|
|
37
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r,e.tokenId,e.key,e.requestHash,e.operationId??null,e.responseStatus,JSON.stringify(e.responseBody),i,n]),this.getIdempotency(e.tokenId,e.key)}purgeExpired(){let e=this.now(),t=this.controlPlane.database.run("DELETE FROM api_tokens WHERE (expires_at < ? OR revoked_at IS NOT NULL) AND created_at < ?",[e,new Date(this.nowFn().getTime()-2592000000).toISOString()]).changes,r=this.controlPlane.database.run("DELETE FROM api_idempotency_records WHERE expires_at < ?",[e]).changes;return{tokens:t,idempotency:r}}}class va{region;client;constructor(e="us-east-1",t=new u){this.region=e;this.client=t}request(e,t){return this.client.request({service:"backup",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`CryoControllerFrontendService.${e}`},body:JSON.stringify(t)})}startBackupJob(e){return this.request("StartBackupJob",e)}describeBackupJob(e){return this.request("DescribeBackupJob",{BackupJobId:e})}startRestoreJob(e){return this.request("StartRestoreJob",e)}describeRestoreJob(e){return this.request("DescribeRestoreJob",{RestoreJobId:e})}deleteRecoveryPoint(e,t){return this.request("DeleteRecoveryPoint",{BackupVaultName:e,RecoveryPointArn:t})}}class te{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u}async describeCacheClusters(e){let t={Action:"DescribeCacheClusters",Version:"2015-02-02",ShowCacheNodeInfo:"true"};if(e)t.CacheClusterId=e;let r=await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(t).toString()});return{CacheClusters:this.parseCacheClusters(r)}}async describeReplicationGroups(e){let t={Action:"DescribeReplicationGroups",Version:"2015-02-02"};if(e)t.ReplicationGroupId=e;let r=await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(t).toString()});return{ReplicationGroups:[]}}async createCacheCluster(e){let t={Action:"CreateCacheCluster",Version:"2015-02-02",CacheClusterId:e.cacheClusterId,Engine:e.engine,CacheNodeType:e.cacheNodeType};if(e.numCacheNodes)t.NumCacheNodes=e.numCacheNodes;if(e.engineVersion)t.EngineVersion=e.engineVersion;if(e.port)t.Port=e.port;if(e.securityGroupIds&&e.securityGroupIds.length>0)e.securityGroupIds.forEach((n,i)=>{t[`SecurityGroupIds.member.${i+1}`]=n});if(e.subnetGroupName)t.CacheSubnetGroupName=e.subnetGroupName;if(e.tags&&e.tags.length>0)e.tags.forEach((n,i)=>{t[`Tags.member.${i+1}.Key`]=n.Key,t[`Tags.member.${i+1}.Value`]=n.Value});let r=await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(t).toString()});return{CacheCluster:this.parseCacheCluster(r)}}async deleteCacheCluster(e,t){let r={Action:"DeleteCacheCluster",Version:"2015-02-02",CacheClusterId:e};if(t)r.FinalSnapshotIdentifier=t;await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(r).toString()})}async rebootCacheCluster(e,t){let r={Action:"RebootCacheCluster",Version:"2015-02-02",CacheClusterId:e};t.forEach((n,i)=>{r[`CacheNodeIdsToReboot.member.${i+1}`]=n}),await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(r).toString()})}async describeCacheEngineVersions(e){let t={Action:"DescribeCacheEngineVersions",Version:"2015-02-02"};if(e)t.Engine=e;let r=await this.client.request({service:"elasticache",region:this.region,method:"POST",path:"/",body:new URLSearchParams(t).toString()});return{CacheEngineVersions:[]}}async getCacheStatistics(e){let t=await this.describeCacheClusters(e);if(!t.CacheClusters||t.CacheClusters.length===0)throw Error(`Cache cluster ${e} not found`);return{cpuUtilization:0,evictions:0,hits:0,misses:0,connections:0}}parseCacheClusters(e){if(e.CacheClusterId)return[{CacheClusterId:e.CacheClusterId,CacheClusterStatus:e.CacheClusterStatus||"available",Engine:e.Engine||"redis",EngineVersion:e.EngineVersion||"7.0",CacheNodeType:e.CacheNodeType||"cache.t3.micro",NumCacheNodes:Number.parseInt(e.NumCacheNodes||"1"),CacheClusterCreateTime:e.CacheClusterCreateTime||new Date().toISOString()}];return[]}parseCacheCluster(e){return{CacheClusterId:e.CacheClusterId,CacheClusterStatus:e.CacheClusterStatus||"creating",Engine:e.Engine||"redis",EngineVersion:e.EngineVersion||"7.0",CacheNodeType:e.CacheNodeType||"cache.t3.micro",NumCacheNodes:Number.parseInt(e.NumCacheNodes||"1"),CacheClusterCreateTime:e.CacheClusterCreateTime||new Date().toISOString()}}}import{isIP as Bg}from"node:net";var QS={every_minute:"* * * * *",every_five_minutes:"*/5 * * * *",hourly:"0 * * * *",daily:"0 0 * * *",weekly:"0 0 * * 0"},YS={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12},Og={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6};function _g(e){try{return new Intl.DateTimeFormat("en",{timeZone:e}).format(new Date),e}catch{throw Error(`Unknown schedule timezone: ${e}`)}}function ic(e,t,r,n){let i=t[e.toUpperCase()]??Number(e);if(!Number.isInteger(i)||i<r||i>n)throw Error(`Schedule field value ${e} is outside ${r}-${n}.`);return i}function Ps(e,t,r,n={},i){if(e==="*"||e==="?")return;let o=new Set;for(let s of e.split(",")){let[c,l]=s.split("/"),a=l?ic(l,{},1,r-t+1):1,m,E;if(c==="*")m=t,E=r;else if(c.includes("-")){let k=c.split("-");m=ic(k[0],n,t,r),E=ic(k[1],n,t,r)}else m=ic(c,n,t,r),E=m;if(E<m)throw Error("Schedule ranges must be ascending.");for(let k=m;k<=E;k+=a)o.add(i?i(k):k===7&&r===7?0:k)}return o}function XS(e,t){let r=Object.fromEntries(new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"numeric",day:"numeric",weekday:"short",hour:"numeric",minute:"numeric",hourCycle:"h23"}).formatToParts(e).map((n)=>[n.type,n.value]));return{minute:Number(r.minute),hour:Number(r.hour),day:Number(r.day),month:Number(r.month),weekday:Og[r.weekday.toUpperCase()],year:Number(r.year),key:`${r.year}-${r.month}-${r.day} ${r.hour}:${r.minute}`}}function Ng(e){let r=(e.startsWith("cron(")?e.slice(5,-1).trim():e.trim()).split(/\s+/);if(r.length!==5&&r.length!==6)throw Error("Cron schedules require five standard fields or six EventBridge fields.");let[n,i,o,s,c,l]=r,a=r.length===6;return{minute:Ps(n,0,59),hour:Ps(i,0,23),day:Ps(o,1,31),month:Ps(s,1,12,YS),weekday:Ps(c,a?1:0,7,Og,a?(m)=>m===7?6:m-1:void 0),year:l?Ps(l,1970,2199):void 0,dayWildcard:o==="*"||o==="?",weekdayWildcard:c==="*"||c==="?"}}function ZS(e,t){if(!((!t.minute||t.minute.has(e.minute))&&(!t.hour||t.hour.has(e.hour))&&(!t.month||t.month.has(e.month))&&(!t.year||t.year.has(e.year))))return!1;let n=!t.day||t.day.has(e.day),i=!t.weekday||t.weekday.has(e.weekday);return t.dayWildcard?i:t.weekdayWildcard?n:n||i}function $g(e){let t=/^rate\(\s*(\d+)\s+(minute|minutes|hour|hours|day|days)\s*\)$/i.exec(e);if(!t)return;let r=Number(t[1]);if(r<1)throw Error("Rate amount must be positive.");return r*(t[2].toLowerCase().startsWith("minute")?60000:t[2].toLowerCase().startsWith("hour")?3600000:86400000)}function xs(e){let t=e.trim(),r=QS[t.toLowerCase()]??t;if(!r)throw Error("Schedule expression is required.");let n=$g(r);if(n){let i=n/60000;return{original:t,normalized:`rate(${i} minutes)`,kind:"rate",description:i%1440===0?`Every ${i/1440} day(s)`:i%60===0?`Every ${i/60} hour(s)`:`Every ${i} minute(s)`}}return Ng(r),{original:t,normalized:r.startsWith("cron(")?r:`cron(${r})`,kind:"cron",description:`Cron ${r.replace(/^cron\(|\)$/g,"")}`}}function tt(e,t,r=new Date,n=5){let i=xs(e),o=_g(t),s=Math.min(20,Math.max(1,n)),c=$g(i.normalized);if(c)return Array.from({length:s},(O,q)=>new Date(r.getTime()+c*(q+1)).toISOString());let l=Ng(i.normalized),a=[],m=new Set,E=new Date(Math.floor(r.getTime()/60000)*60000+60000),k=0;while(a.length<s&&k<1100000){let O=XS(E,o);if(ZS(O,l)&&!m.has(O.key))a.push(E.toISOString()),m.add(O.key);E=new Date(E.getTime()+60000),k++}if(a.length<s)throw Error("Schedule produced no runs within the bounded preview horizon.");return a}function rt(e,t="UTC",r=new Date,n=5){let i=xs(e),o=tt(i.normalized,t,r,n),s=i.kind==="cron"?["Server cron and EventBridge use the same wall-clock preview; provider-specific extensions are retained only when supported."]:["Rate schedules use elapsed-time intervals and are not shifted by DST."];return{...i,timezone:_g(t),nextRuns:o,capabilities:{server:i.kind==="cron",eventbridge:!0,notes:s}}}function $n(e){let t=xs(e.expression),r=t.normalized.slice(5,-1).trim().split(/\s+/),n=t.kind==="cron"&&r.length===5;if(e.provider==="server")return{provider:"server",supported:n,features:{timezone:!0,flexibleWindow:!1,catchUp:!1,replaceOverlap:!1},notes:[t.kind==="rate"?"Server cron requires a cron expression; use an equivalent cron schedule.":r.length!==5?"EventBridge six-field cron extensions cannot be installed as server cron.":"Cron is reconciled through a root-owned ts-cloud entry.",e.missedRunPolicy==="catch_up"?"Catch-up is handled by the control plane, not cron.":"Missed runs are skipped by cron."]};if(e.provider==="eventbridge")return{provider:"eventbridge",supported:!0,features:{timezone:!0,flexibleWindow:!0,catchUp:!1,replaceOverlap:!1},notes:["Five-field cron is translated explicitly to EventBridge six-field syntax. Flexible windows are provider-native; overlap and catch-up remain control-plane policies."]};if(e.provider==="lambda")return{provider:"lambda",supported:!0,features:{timezone:!0,flexibleWindow:!0,catchUp:!1,replaceOverlap:!1},notes:["The schedule invokes one immutable Lambda target."]};return{provider:"platform",supported:!0,features:{timezone:!0,flexibleWindow:!0,catchUp:!0,replaceOverlap:!0},notes:["The durable control-plane worker enforces all configured policies."]}}function ev(e){if(e.queues===!0)return[{queue:"default",processes:e.queueConcurrency??1}];if(!Array.isArray(e.queues))return[];return e.queues.map((t)=>{if(typeof t==="string")return{queue:t,processes:e.queueConcurrency??1};let[r,n]=Object.entries(t)[0]??["default",e.queueConcurrency??1];return{queue:r,processes:n}})}function $r(e,t,r){let n=new Set,i=new Set,o=new Map(r.resources.map((E)=>[E.slug,E])),s=0,c=0;for(let[E,k]of Object.entries(t.sites??{})){let O=o.get(E);if(k.scheduler){let Y=`config:site:${E}:scheduler`;n.add(Y),e.upsertConfigJob({organizationId:r.organization.id,projectId:r.project.id,environmentId:r.environment.id,resourceId:O?.id,name:`${E} scheduler`,provider:"server",expression:"* * * * *",timezone:"UTC",flexibleMinutes:0,target:{kind:"dashboard_operation",operationId:`scheduler:run:${E}`},payloadRefs:{},missedRunPolicy:"skip",overlapPolicy:"forbid",retryPolicy:{maxAttempts:3,backoffSeconds:30},timeoutSeconds:300,enabled:!0,origin:"config",sourceKey:Y,observedState:{source:"cloud.config.ts"},reconciliationStatus:"pending"}),s++}let q=k,G=Array.isArray(q.queues??q.workers)?q.queues??q.workers:[];for(let[Y,re]of G.entries()){let he=typeof re==="string"?{queue:re}:re,ee=String(he.queue??he.name??"default"),Re=`config:site:${E}:worker:${Y}:${ee}`;i.add(Re),e.upsertWorker({organizationId:r.organization.id,projectId:r.project.id,environmentId:r.environment.id,resourceId:O?.id,name:`${E}:${ee}`,provider:"systemd",queue:ee,processes:Number(he.processes)||1,timeoutSeconds:Number(he.timeout)||60,restartPolicy:"always",target:{operationId:`worker:restart:${E}`,site:E},enabled:!0,origin:"config",sourceKey:Re,observedState:{source:"cloud.config.ts",currentJob:null,failures:0},reconciliationStatus:"pending"}),c++}}let l=t.infrastructure?.compute?.backups;if(l?.enabled)n.add("config:platform:backup"),e.upsertConfigJob({organizationId:r.organization.id,projectId:r.project.id,environmentId:r.environment.id,name:"Scheduled backup",provider:"server",expression:String(l.schedule??"0 2 * * *"),timezone:String(l.timezone??"UTC"),flexibleMinutes:0,target:{kind:"dashboard_operation",operationId:"backup:run"},payloadRefs:{},missedRunPolicy:"skip",overlapPolicy:"forbid",retryPolicy:{maxAttempts:3,backoffSeconds:60},timeoutSeconds:3600,enabled:!0,origin:"config",sourceKey:"config:platform:backup",observedState:{source:"cloud.config.ts"},reconciliationStatus:"pending"}),s++;let a=t.environments?.[r.environment.slug]?.app;if(a){if(a.scheduler!=="off"){let E=`config:serverless:${r.environment.slug}:scheduler`;n.add(E),e.upsertConfigJob({organizationId:r.organization.id,projectId:r.project.id,environmentId:r.environment.id,name:`${r.environment.name} serverless scheduler`,provider:"eventbridge",expression:"rate(1 minute)",timezone:"UTC",flexibleMinutes:0,target:{kind:"serverless_scheduler",action:"schedule:run"},payloadRefs:{},missedRunPolicy:a.scheduler==="sub-minute"?"catch_up":"skip",overlapPolicy:"forbid",retryPolicy:{maxAttempts:3,backoffSeconds:30},timeoutSeconds:a.cliTimeout??900,enabled:!0,origin:"config",sourceKey:E,observedState:{source:"cloud.config.ts",mode:a.scheduler??"on"},reconciliationStatus:"pending"}),s++}for(let{queue:E,processes:k}of ev(a)){let O=`config:serverless:${r.environment.slug}:worker:${E}`;i.add(O),e.upsertWorker({organizationId:r.organization.id,projectId:r.project.id,environmentId:r.environment.id,name:`${r.environment.name}:${E}`,provider:"lambda",queue:E,processes:k,timeoutSeconds:a.queueTimeout??120,restartPolicy:"on_failure",target:{function:"queue",queue:E},enabled:!0,origin:"config",sourceKey:O,observedState:{source:"cloud.config.ts",currentJob:null,failures:0},reconciliationStatus:"pending"}),c++}}let m=0;for(let E of e.list(r.project.id,{environmentId:r.environment.id}).filter((k)=>k.origin==="config"&&k.sourceKey&&!n.has(k.sourceKey)))e.reconcile(E.id,"drifted",{...E.observedState,reason:"Definition is no longer present in configuration; retained for non-destructive review."}),m++;for(let E of e.listWorkers(r.project.id,r.environment.id).filter((k)=>k.origin==="config"&&k.sourceKey&&!i.has(k.sourceKey)))e.reconcileWorker(E.id,"drifted",{...E.observedState,reason:"Definition is no longer present in configuration; retained for non-destructive review."}),m++;return{jobs:s,workers:c,drifted:m}}class On{store;queue;constructor(e,t={}){this.store=e;this.queue=t.queue??new b(e.controlPlane)}enqueue(e,t){let r=new Date(t.scheduledFor??this.store.now()).toISOString(),n=`${e.id}:${t.trigger==="manual"?crypto.randomUUID():r}`,i=this.store.activeExecution(e.id);if(i&&e.overlapPolicy==="forbid")return this.store.createExecution({jobId:e.id,trigger:t.trigger,scheduledFor:r,idempotencyKey:n,status:"skipped",output:{reason:"overlap_forbidden",activeExecutionId:i.id}});if(i&&e.overlapPolicy==="replace"&&i.operationId)try{this.queue.requestCancellation(i.operationId,t.actorId)}catch{}let o=this.store.createExecution({jobId:e.id,trigger:t.trigger,scheduledFor:r,idempotencyKey:n,status:"queued",output:{semantics:"at_least_once"}});if(o.operationId)return o;let s=this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:t.actorId,kind:"job.execute",input:{jobId:e.id,executionId:o.id},idempotencyKey:`job-execution:${o.id}`,lockKey:e.overlapPolicy==="allow"?`job-execution:${o.id}`:`job:${e.id}`,maxAttempts:e.retryPolicy.maxAttempts,timeoutSeconds:e.timeoutSeconds,retryClasses:["job_transient"],resumePolicy:"requeue"}).operation;return this.store.attachOperation(o.id,s.id)}tick(e=this.store.now()){let t=[];for(let r of this.store.due(e.toISOString())){let n=r.nextRunAt,i=tt(r.normalizedExpression,r.timezone,e,1)[0];if(r.missedRunPolicy==="catch_up"){let o=n,s=0;while(o<=e.toISOString()&&s<10)t.push(this.enqueue(r,{trigger:o===n?"scheduled":"catch_up",scheduledFor:o})),o=tt(r.normalizedExpression,r.timezone,new Date(o),1)[0],s++}else t.push(this.enqueue(r,{trigger:"scheduled",scheduledFor:n}));this.store.markScheduled(r.id,n,i)}return t}}function Mg(e){return{"job.execute":async(r)=>{let n=r.operation.input&&typeof r.operation.input==="object"&&!Array.isArray(r.operation.input)?r.operation.input:{},i=e.store.get(String(n.jobId??"")),o=e.store.getExecution(String(n.executionId??""));if(!i||!o)throw Error("Scheduled job execution is no longer available.");e.store.transitionExecution(o.id,"running",{attempt:r.operation.attempt}),r.checkpoint("execute",`Running ${i.name} on ${i.provider}.`),r.log(`Trigger ${o.trigger}; scheduled for ${o.scheduledFor}; semantics at-least-once.`,{stream:"system"});let s=await e.executor(i,i.target,r);if(s.stdout)r.log(s.stdout,{stream:"stdout"});if(s.stderr)r.log(s.stderr,{stream:"stderr"});if(!s.ok){if(e.store.transitionExecution(o.id,r.operation.attempt>=i.retryPolicy.maxAttempts?"dead":"failed",{attempt:r.operation.attempt,error:s.stderr??"Job execution failed."}),s.retryable)throw new _e(s.stderr??"Scheduled job failed transiently.","job_transient");throw Error(s.stderr??"Scheduled job failed.")}return e.store.transitionExecution(o.id,"succeeded",{attempt:r.operation.attempt,output:s.output??{}}),{jobId:i.id,executionId:o.id,provider:i.provider}}}}var Kr=(e)=>typeof e==="string"&&e?e:void 0,Lg=(e)=>Number(e)===1,rs=(e)=>{try{return JSON.parse(String(e))}catch{return{}}},Eo=(e,t,r,n)=>{let i=Number(e);return Number.isFinite(i)?Math.min(n,Math.max(r,Math.floor(i))):t};function oc(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:Kr(e.environment_id),resourceId:Kr(e.resource_id),name:String(e.name),provider:String(e.provider),expression:String(e.expression),normalizedExpression:String(e.normalized_expression),timezone:String(e.timezone),startsAt:Kr(e.starts_at),endsAt:Kr(e.ends_at),flexibleMinutes:Number(e.flexible_minutes),target:rs(e.target),payloadRefs:rs(e.payload_refs),missedRunPolicy:String(e.missed_run_policy),overlapPolicy:String(e.overlap_policy),retryPolicy:rs(e.retry_policy),timeoutSeconds:Number(e.timeout_seconds),enabled:Lg(e.enabled),origin:String(e.origin),sourceKey:Kr(e.source_key),ownerActorId:Kr(e.owner_actor_id),observedState:rs(e.observed_state),reconciliationStatus:String(e.reconciliation_status),nextRunAt:Kr(e.next_run_at),lastScheduledFor:Kr(e.last_scheduled_for),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function sc(e){return{id:String(e.id),jobId:String(e.job_id),operationId:Kr(e.operation_id),trigger:String(e.trigger),scheduledFor:String(e.scheduled_for),idempotencyKey:String(e.idempotency_key),status:String(e.status),attempt:Number(e.attempt),startedAt:Kr(e.started_at),finishedAt:Kr(e.finished_at),output:rs(e.output),error:Kr(e.error),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function cu(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:Kr(e.environment_id),resourceId:Kr(e.resource_id),name:String(e.name),provider:String(e.provider),queue:String(e.queue),processes:Number(e.processes),timeoutSeconds:Number(e.timeout_seconds),restartPolicy:String(e.restart_policy),target:rs(e.target),enabled:Lg(e.enabled),origin:String(e.origin),sourceKey:Kr(e.source_key),ownerActorId:Kr(e.owner_actor_id),observedState:rs(e.observed_state),reconciliationStatus:String(e.reconciliation_status),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class _r{controlPlane;options;constructor(e,t={}){this.controlPlane=e;this.options=t}now(){return this.options.now?.()??new Date}create(e){if(!e.name.trim())throw Error("Scheduled jobs require a name.");let t=rt(e.expression,e.timezone,this.now(),1),r=crypto.randomUUID(),n=this.now().toISOString(),i=e.startsAt?new Date(e.startsAt).toISOString():void 0,o=e.endsAt?new Date(e.endsAt).toISOString():void 0;if(i&&o&&i>=o)throw Error("Schedule start must be before end.");let s=t.nextRuns.find((c)=>(!i||c>=i)&&(!o||c<=o));return this.controlPlane.database.run("INSERT INTO scheduled_jobs (id,organization_id,project_id,environment_id,resource_id,name,provider,expression,normalized_expression,timezone,starts_at,ends_at,flexible_minutes,target,payload_refs,missed_run_policy,overlap_policy,retry_policy,timeout_seconds,enabled,origin,source_key,owner_actor_id,observed_state,reconciliation_status,next_run_at,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[r,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.name.trim().slice(0,120),e.provider,e.expression,t.normalized,e.timezone,i??null,o??null,Eo(e.flexibleMinutes,0,0,1440),JSON.stringify(e.target),JSON.stringify(e.payloadRefs),e.missedRunPolicy,e.overlapPolicy,JSON.stringify({maxAttempts:Eo(e.retryPolicy.maxAttempts,3,1,20),backoffSeconds:Eo(e.retryPolicy.backoffSeconds,30,0,86400),deadLetterRef:e.retryPolicy.deadLetterRef}),Eo(e.timeoutSeconds,900,1,86400),e.enabled?1:0,e.origin,e.sourceKey??null,e.ownerActorId??null,JSON.stringify(e.observedState),e.reconciliationStatus,s??null,1,n,n]),this.get(r)}get(e){let t=this.controlPlane.database.query("SELECT * FROM scheduled_jobs WHERE id=?").get(e);return t?oc(t):void 0}getBySource(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM scheduled_jobs WHERE project_id=? AND environment_id IS ? AND source_key=?").get(e,t??null,r);return n?oc(n):void 0}list(e,t={}){let r=["project_id=?"],n=[e];if(t.environmentId)r.push("environment_id=?"),n.push(t.environmentId);if(t.resourceIds?.length)r.push(`resource_id IN (${t.resourceIds.map(()=>"?").join(",")})`),n.push(...t.resourceIds);if(t.enabled!=null)r.push("enabled=?"),n.push(t.enabled?1:0);return this.controlPlane.database.query(`SELECT * FROM scheduled_jobs WHERE ${r.join(" AND ")} ORDER BY next_run_at IS NULL,next_run_at,name`).all(...n).map(oc)}setEnabled(e,t){this.controlPlane.database.run("UPDATE scheduled_jobs SET enabled=?,version=version+1,updated_at=? WHERE id=?",[t?1:0,this.now().toISOString(),e]);let r=this.get(e);if(!r)throw Error("Scheduled job was not found.");return r}updateSchedule(e,t){let r=this.get(e);if(!r)throw Error("Scheduled job was not found.");let n=t.expression??r.expression,i=t.timezone??r.timezone,o=rt(n,i,this.now(),1),s=this.now().toISOString();return this.controlPlane.database.run("UPDATE scheduled_jobs SET expression=?,normalized_expression=?,timezone=?,missed_run_policy=?,overlap_policy=?,timeout_seconds=?,next_run_at=?,reconciliation_status=?,version=version+1,updated_at=? WHERE id=?",[n,o.normalized,i,t.missedRunPolicy??r.missedRunPolicy,t.overlapPolicy??r.overlapPolicy,Eo(t.timeoutSeconds,r.timeoutSeconds,1,86400),o.nextRuns[0],"pending",s,e]),this.get(e)}remove(e){let t=this.get(e);if(!t)throw Error("Scheduled job was not found.");if(t.origin==="config")throw Error("Config-defined jobs must be removed from configuration, not destructively deleted.");this.controlPlane.database.run("DELETE FROM scheduled_jobs WHERE id=?",[e])}markScheduled(e,t,r){this.controlPlane.database.run("UPDATE scheduled_jobs SET last_scheduled_for=?,next_run_at=?,updated_at=? WHERE id=?",[t,r??null,this.now().toISOString(),e])}reconcile(e,t,r){return this.controlPlane.database.run("UPDATE scheduled_jobs SET reconciliation_status=?,observed_state=?,updated_at=? WHERE id=?",[t,JSON.stringify(r),this.now().toISOString(),e]),this.get(e)}upsertConfigJob(e){let t=this.getBySource(e.projectId,e.environmentId,e.sourceKey);if(!t)return this.create(e);let r=rt(e.expression,e.timezone,this.now(),1),n=this.now().toISOString();if(t.resourceId===e.resourceId&&t.name===e.name&&t.provider===e.provider&&t.expression===e.expression&&t.normalizedExpression===r.normalized&&t.timezone===e.timezone&&JSON.stringify(t.target)===JSON.stringify(e.target)&&JSON.stringify(t.payloadRefs)===JSON.stringify(e.payloadRefs)&&t.missedRunPolicy===e.missedRunPolicy&&t.overlapPolicy===e.overlapPolicy&&JSON.stringify(t.retryPolicy)===JSON.stringify(e.retryPolicy)&&t.timeoutSeconds===e.timeoutSeconds&&t.enabled===e.enabled)return t;return this.controlPlane.database.run("UPDATE scheduled_jobs SET resource_id=?,name=?,provider=?,expression=?,normalized_expression=?,timezone=?,target=?,payload_refs=?,missed_run_policy=?,overlap_policy=?,retry_policy=?,timeout_seconds=?,enabled=?,observed_state=?,reconciliation_status=?,next_run_at=COALESCE(next_run_at,?),version=version+1,updated_at=? WHERE id=?",[e.resourceId??null,e.name,e.provider,e.expression,r.normalized,e.timezone,JSON.stringify(e.target),JSON.stringify(e.payloadRefs),e.missedRunPolicy,e.overlapPolicy,JSON.stringify(e.retryPolicy),e.timeoutSeconds,e.enabled?1:0,JSON.stringify(e.observedState),e.reconciliationStatus,r.nextRuns[0],n,t.id]),this.get(t.id)}due(e=this.now().toISOString()){return this.controlPlane.database.query("SELECT * FROM scheduled_jobs WHERE enabled=1 AND next_run_at IS NOT NULL AND next_run_at<=? AND (starts_at IS NULL OR starts_at<=?) AND (ends_at IS NULL OR ends_at>=?) ORDER BY next_run_at LIMIT 200").all(e,e,e).map(oc)}createExecution(e){let t=this.controlPlane.database.query("SELECT * FROM job_executions WHERE idempotency_key=?").get(e.idempotencyKey);if(t)return sc(t);let r=crypto.randomUUID(),n=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO job_executions (id,job_id,operation_id,trigger,scheduled_for,idempotency_key,status,attempt,output,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)",[r,e.jobId,e.operationId??null,e.trigger,e.scheduledFor,e.idempotencyKey,e.status,0,JSON.stringify(e.output),n,n]),this.getExecution(r)}getExecution(e){let t=this.controlPlane.database.query("SELECT * FROM job_executions WHERE id=?").get(e);return t?sc(t):void 0}listExecutions(e,t=100){return this.controlPlane.database.query("SELECT * FROM job_executions WHERE job_id=? ORDER BY scheduled_for DESC,created_at DESC LIMIT ?").all(e,Math.min(1000,Math.max(1,t))).map(sc)}activeExecution(e){let t=this.controlPlane.database.query("SELECT * FROM job_executions WHERE job_id=? AND status IN ('queued','running') ORDER BY created_at DESC LIMIT 1").get(e);return t?sc(t):void 0}attachOperation(e,t){return this.controlPlane.database.run("UPDATE job_executions SET operation_id=?,updated_at=? WHERE id=?",[t,this.now().toISOString(),e]),this.getExecution(e)}transitionExecution(e,t,r={}){let n=this.now().toISOString(),i=t==="running"?n:null,o=["succeeded","failed","skipped","dead"].includes(t)?n:null;return this.controlPlane.database.run("UPDATE job_executions SET status=?,attempt=COALESCE(?,attempt),started_at=COALESCE(started_at,?),finished_at=?,output=COALESCE(?,output),error=?,updated_at=? WHERE id=?",[t,r.attempt??null,i,o,r.output?JSON.stringify(r.output):null,r.error?.slice(0,2000)??null,n,e]),this.getExecution(e)}upsertWorker(e){let t=e.sourceKey?this.controlPlane.database.query("SELECT * FROM worker_definitions WHERE project_id=? AND source_key=? AND environment_id IS ?").get(e.projectId,e.sourceKey,e.environmentId??null):void 0,r=t?cu(t):void 0,n=r?.id??crypto.randomUUID(),i=this.now().toISOString(),o=Eo(e.processes,1,0,1000),s=Eo(e.timeoutSeconds,60,1,86400);if(r&&r.resourceId===e.resourceId&&r.name===e.name.slice(0,120)&&r.provider===e.provider&&r.queue===e.queue.slice(0,200)&&r.processes===o&&r.timeoutSeconds===s&&r.restartPolicy===e.restartPolicy&&JSON.stringify(r.target)===JSON.stringify(e.target)&&r.enabled===e.enabled)return r;return this.controlPlane.database.run("INSERT INTO worker_definitions (id,organization_id,project_id,environment_id,resource_id,name,provider,queue,processes,timeout_seconds,restart_policy,target,enabled,origin,source_key,owner_actor_id,observed_state,reconciliation_status,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET name=excluded.name,resource_id=excluded.resource_id,provider=excluded.provider,queue=excluded.queue,processes=excluded.processes,timeout_seconds=excluded.timeout_seconds,restart_policy=excluded.restart_policy,target=excluded.target,enabled=excluded.enabled,observed_state=excluded.observed_state,reconciliation_status=excluded.reconciliation_status,version=worker_definitions.version+1,updated_at=excluded.updated_at",[n,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.name.slice(0,120),e.provider,e.queue.slice(0,200),o,s,e.restartPolicy,JSON.stringify(e.target),e.enabled?1:0,e.origin,e.sourceKey??null,e.ownerActorId??null,JSON.stringify(e.observedState),e.reconciliationStatus,1,r?.createdAt??i,i]),this.getWorker(n)}getWorker(e){let t=this.controlPlane.database.query("SELECT * FROM worker_definitions WHERE id=?").get(e);return t?cu(t):void 0}listWorkers(e,t){return this.controlPlane.database.query(`SELECT * FROM worker_definitions WHERE project_id=?${t?" AND environment_id=?":""} ORDER BY name`).all(e,...t?[t]:[]).map(cu)}setWorkerProcesses(e,t){this.controlPlane.database.run("UPDATE worker_definitions SET processes=?,reconciliation_status='pending',version=version+1,updated_at=? WHERE id=?",[Eo(t,1,0,1000),this.now().toISOString(),e]);let r=this.getWorker(e);if(!r)throw Error("Worker was not found.");return r}reconcileWorker(e,t,r){this.controlPlane.database.run("UPDATE worker_definitions SET reconciliation_status=?,observed_state=?,updated_at=? WHERE id=?",[t,JSON.stringify(r),this.now().toISOString(),e]);let n=this.getWorker(e);if(!n)throw Error("Worker was not found.");return n}}var gt=(e)=>e==null?void 0:String(e),ac=(e)=>Number(e)===1,To=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}};function jg(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),name:String(e.name),provider:String(e.provider),endpoint:gt(e.endpoint),endpointPolicy:String(e.endpoint_policy),bucket:gt(e.bucket),prefix:String(e.prefix),region:gt(e.region),forcePathStyle:ac(e.force_path_style),credentialRef:gt(e.credential_ref),encryption:String(e.encryption),encryptionKeyRef:gt(e.encryption_key_ref),immutability:To(e.immutability,{}),status:String(e.status),lastTestedAt:gt(e.last_tested_at),lastSuccessAt:gt(e.last_success_at),lastFailureAt:gt(e.last_failure_at),lastError:gt(e.last_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function du(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:gt(e.environment_id),resourceId:gt(e.resource_id),dataServiceId:gt(e.data_service_id),destinationId:String(e.destination_id),name:String(e.name),resourceKind:String(e.resource_kind),schedule:String(e.schedule),timezone:String(e.timezone),retention:To(e.retention,{}),compression:String(e.compression),encryption:String(e.encryption),includePatterns:To(e.include_patterns,[]),excludePatterns:To(e.exclude_patterns,[]),expectedRpoMinutes:Number(e.expected_rpo_minutes),expectedRtoMinutes:Number(e.expected_rto_minutes),healthCheckId:gt(e.health_check_id),enabled:ac(e.enabled),nextRunAt:gt(e.next_run_at),lastRunAt:gt(e.last_run_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function uu(e){return{id:String(e.id),projectId:String(e.project_id),policyId:gt(e.policy_id),destinationId:String(e.destination_id),resourceId:gt(e.resource_id),dataServiceId:gt(e.data_service_id),backupJobId:gt(e.backup_job_id),kind:String(e.kind),pointInTime:String(e.point_in_time),uri:String(e.uri),sizeBytes:Number(e.size_bytes),checksum:String(e.checksum),manifest:To(e.manifest,{}),toolVersion:gt(e.tool_version),engineVersion:gt(e.engine_version),expiresAt:gt(e.expires_at),lockedUntil:gt(e.locked_until),held:ac(e.held),pinned:ac(e.pinned),status:String(e.status),verificationState:String(e.verification_state),verifiedAt:gt(e.verified_at),durationMs:e.duration_ms==null?void 0:Number(e.duration_ms),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function lu(e){return{id:String(e.id),projectId:String(e.project_id),policyId:gt(e.policy_id),recoveryPointId:gt(e.recovery_point_id),operationId:gt(e.operation_id),kind:String(e.kind),status:String(e.status),idempotencyKey:String(e.idempotency_key),target:To(e.target,{}),restoreMode:gt(e.restore_mode),cancellability:String(e.cancellability),safetyBackupId:gt(e.safety_backup_id),healthResult:e.health_result?To(e.health_result,{}):void 0,progress:To(e.progress,{}),error:gt(e.error),startedAt:gt(e.started_at),finishedAt:gt(e.finished_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function tv(e){let t=e.toLowerCase();if(t==="localhost"||t.endsWith(".localhost")||t.endsWith(".local")||t.endsWith(".internal"))return!0;if(Bg(t)===6)return t==="::1"||t.startsWith("fe80:");if(Bg(t)!==4)return!1;let[r,n]=t.split(".").map(Number);return r===10||r===127||r===0||r===169&&n===254||r===172&&n>=16&&n<=31||r===192&&n===168}function rv(e){if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.name))throw Error("Backup destination names must be 2-63 lowercase letters, numbers, or dashes.");if(e.provider!=="aws_backup"&&!e.bucket)throw Error("S3 backup destinations require a bucket.");if(e.provider==="s3_compatible"&&!e.endpoint)throw Error("S3-compatible destinations require an explicit endpoint.");if(e.provider==="s3_compatible"&&!e.credentialRef)throw Error("S3-compatible destinations require a credential reference.");if(e.encryption!=="provider"&&!e.encryptionKeyRef)throw Error("Client-side encryption requires an encryption key reference.");if(e.endpoint){let t=new URL(e.endpoint);if(t.protocol!=="https:"||t.username||t.password||t.search||t.hash||t.pathname!=="/")throw Error("Backup endpoints must be origin-only HTTPS URLs without credentials, paths, queries, or fragments.");if(tv(t.hostname)&&e.endpointPolicy!=="allow_private")throw Error("Private backup endpoints require endpointPolicy allow_private.")}}class Ln{controlPlane;now;constructor(e,t=()=>new Date){this.controlPlane=e;this.now=t}createDestination(e){rv(e);let t=crypto.randomUUID(),r=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO backup_destinations (id,organization_id,project_id,name,provider,endpoint,endpoint_policy,bucket,prefix,region,force_path_style,credential_ref,encryption,encryption_key_ref,immutability,status,last_tested_at,last_success_at,last_failure_at,last_error,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.organizationId,e.projectId,e.name,e.provider,e.endpoint??null,e.endpointPolicy,e.bucket??null,e.prefix,e.region??null,e.forcePathStyle?1:0,e.credentialRef??null,e.encryption,e.encryptionKeyRef??null,JSON.stringify(e.immutability),e.status,e.lastTestedAt??null,e.lastSuccessAt??null,e.lastFailureAt??null,e.lastError??null,1,r,r]),this.getDestination(t)}getDestination(e){let t=this.controlPlane.database.query("SELECT * FROM backup_destinations WHERE id=?").get(e);return t?jg(t):void 0}listDestinations(e){return this.controlPlane.database.query("SELECT * FROM backup_destinations WHERE project_id=? ORDER BY name").all(e).map(jg)}recordDestinationTest(e,t){let r=this.now().toISOString();return this.controlPlane.database.run("UPDATE backup_destinations SET status=?,last_tested_at=?,last_success_at=CASE WHEN ? THEN ? ELSE last_success_at END,last_failure_at=CASE WHEN ? THEN last_failure_at ELSE ? END,last_error=?,version=version+1,updated_at=? WHERE id=?",[t.ok?"healthy":"failing",r,t.ok?1:0,r,t.ok?1:0,r,t.ok?null:String(t.error??"Destination test failed.").slice(0,1000),r,e]),this.getDestination(e)}createPolicy(e){if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.name))throw Error("Backup policy names must be lowercase slugs.");if(!e.resourceId&&!e.dataServiceId&&!["control_plane","infrastructure"].includes(e.resourceKind))throw Error("A backup policy requires a resource or data service target.");let t=this.getDestination(e.destinationId);if(!t||t.projectId!==e.projectId)throw Error("Backup destination was not found.");if(e.resourceKind==="control_plane"&&t.encryption==="provider")throw Error("Control-plane backups require client-side destination encryption.");if(["logical_database","volume","files","control_plane"].includes(e.resourceKind)&&t.provider==="aws_backup")throw Error(`${e.resourceKind} backups require an object-storage destination.`);if(e.resourceKind==="infrastructure"&&t.provider!=="aws_backup")throw Error("Infrastructure backups require an AWS Backup destination.");let r=xs(e.schedule),n=tt(r.normalized,e.timezone,this.now(),1)[0],i=crypto.randomUUID(),o=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO backup_policies (id,organization_id,project_id,environment_id,resource_id,data_service_id,destination_id,name,resource_kind,schedule,timezone,retention,compression,encryption,include_patterns,exclude_patterns,expected_rpo_minutes,expected_rto_minutes,health_check_id,enabled,next_run_at,last_run_at,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[i,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.dataServiceId??null,e.destinationId,e.name,e.resourceKind,r.normalized,e.timezone,JSON.stringify(e.retention),e.compression,e.encryption,JSON.stringify(e.includePatterns),JSON.stringify(e.excludePatterns),e.expectedRpoMinutes,e.expectedRtoMinutes,e.healthCheckId??null,e.enabled?1:0,n,e.lastRunAt??null,1,o,o]),this.getPolicy(i)}getPolicy(e){let t=this.controlPlane.database.query("SELECT * FROM backup_policies WHERE id=?").get(e);return t?du(t):void 0}listPolicies(e,t){return this.controlPlane.database.query(`SELECT * FROM backup_policies WHERE project_id=?${t?" AND environment_id=?":""} ORDER BY name`).all(e,...t?[t]:[]).map(du)}duePolicies(e=this.now()){return this.controlPlane.database.query("SELECT * FROM backup_policies WHERE enabled=1 AND next_run_at<=? ORDER BY next_run_at,id").all(e.toISOString()).map(du)}advancePolicy(e,t){let r=this.getPolicy(e);if(!r)throw Error("Backup policy was not found.");let n=tt(r.schedule,r.timezone,new Date(t),1)[0];return this.controlPlane.database.run("UPDATE backup_policies SET last_run_at=?,next_run_at=?,version=version+1,updated_at=? WHERE id=?",[t,n,this.now().toISOString(),e]),this.getPolicy(e)}createJob(e){let t=this.controlPlane.database.query("SELECT * FROM backup_jobs WHERE idempotency_key=?").get(e.idempotencyKey);if(t)return lu(t);let r=crypto.randomUUID(),n=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO backup_jobs (id,project_id,policy_id,recovery_point_id,operation_id,kind,status,idempotency_key,target,restore_mode,cancellability,safety_backup_id,health_result,progress,error,started_at,finished_at,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[r,e.projectId,e.policyId??null,e.recoveryPointId??null,e.operationId??null,e.kind,e.status,e.idempotencyKey,JSON.stringify(e.target),e.restoreMode??null,e.cancellability,e.safetyBackupId??null,e.healthResult?JSON.stringify(e.healthResult):null,JSON.stringify(e.progress),e.error??null,e.startedAt??null,e.finishedAt??null,n,n]),this.getJob(r)}getJob(e){let t=this.controlPlane.database.query("SELECT * FROM backup_jobs WHERE id=?").get(e);return t?lu(t):void 0}listJobs(e){return this.controlPlane.database.query("SELECT * FROM backup_jobs WHERE project_id=? ORDER BY created_at DESC").all(e).map(lu)}updateJob(e,t){let r=this.getJob(e);if(!r)throw Error("Backup job was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE backup_jobs SET status=?,operation_id=?,recovery_point_id=?,progress=?,health_result=?,error=?,started_at=?,finished_at=?,safety_backup_id=?,updated_at=? WHERE id=?",[n.status,n.operationId??null,n.recoveryPointId??null,JSON.stringify(n.progress),n.healthResult?JSON.stringify(n.healthResult):null,n.error??null,n.startedAt??null,n.finishedAt??null,n.safetyBackupId??null,this.now().toISOString(),e]),this.getJob(e)}createRecoveryPoint(e){if(!/^sha256:[a-f0-9]{64}$/i.test(e.checksum))throw Error("Recovery points require a SHA-256 checksum.");if(typeof e.uri!=="string"||!["s3:","aws-backup:","file:"].some((n)=>e.uri.startsWith(n)))throw Error("Recovery point URI uses an unsupported destination scheme.");let t=crypto.randomUUID(),r=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO recovery_points (id,project_id,policy_id,destination_id,resource_id,data_service_id,backup_job_id,kind,point_in_time,uri,size_bytes,checksum,manifest,tool_version,engine_version,expires_at,locked_until,held,pinned,status,verification_state,verified_at,duration_ms,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.projectId,e.policyId??null,e.destinationId,e.resourceId??null,e.dataServiceId??null,e.backupJobId??null,e.kind,e.pointInTime,e.uri,e.sizeBytes,e.checksum,JSON.stringify(e.manifest),e.toolVersion??null,e.engineVersion??null,e.expiresAt??null,e.lockedUntil??null,e.held?1:0,e.pinned?1:0,e.status,e.verificationState,e.verifiedAt??null,e.durationMs??null,r,r]),this.getRecoveryPoint(t)}getRecoveryPoint(e){let t=this.controlPlane.database.query("SELECT * FROM recovery_points WHERE id=?").get(e);return t?uu(t):void 0}listRecoveryPoints(e,t){return this.controlPlane.database.query(`SELECT * FROM recovery_points WHERE project_id=?${t?" AND policy_id=?":""} ORDER BY point_in_time DESC`).all(e,...t?[t]:[]).map(uu)}updateRecoveryPoint(e,t){let r=this.getRecoveryPoint(e);if(!r)throw Error("Recovery point was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE recovery_points SET status=?,verification_state=?,verified_at=?,held=?,pinned=?,manifest=?,duration_ms=?,updated_at=? WHERE id=?",[n.status,n.verificationState,n.verifiedAt??null,n.held?1:0,n.pinned?1:0,JSON.stringify(n.manifest),n.durationMs??null,this.now().toISOString(),e]),this.getRecoveryPoint(e)}retentionCandidates(e=this.now()){let t=this.controlPlane.database.query(`SELECT rp.* FROM recovery_points rp
|
|
38
|
+
WHERE rp.status='available' AND rp.held=0 AND rp.pinned=0
|
|
39
|
+
AND rp.expires_at IS NOT NULL AND rp.expires_at<=?
|
|
40
|
+
AND (rp.locked_until IS NULL OR rp.locked_until<=?)
|
|
41
|
+
AND NOT EXISTS (
|
|
42
|
+
SELECT 1 FROM backup_jobs bj WHERE bj.recovery_point_id=rp.id
|
|
43
|
+
AND bj.kind IN ('restore','drill') AND bj.status IN ('queued','running','cleanup_required')
|
|
44
|
+
)
|
|
45
|
+
ORDER BY rp.expires_at,rp.id`).all(e.toISOString(),e.toISOString()).map(uu),r=new Set;for(let n of new Set(t.map((i)=>i.projectId)))for(let i of this.listPolicies(n)){let o=this.listRecoveryPoints(i.projectId,i.id).filter((c)=>c.status==="available").sort((c,l)=>l.pointInTime.localeCompare(c.pointInTime));for(let c of o.slice(0,Math.max(0,i.retention.keepLast??0)))r.add(c.id);let s=[[i.retention.hourly,(c)=>c.toISOString().slice(0,13)],[i.retention.daily,(c)=>c.toISOString().slice(0,10)],[i.retention.weekly,(c)=>new Date(Date.UTC(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()-(c.getUTCDay()+6)%7)).toISOString().slice(0,10)],[i.retention.monthly,(c)=>c.toISOString().slice(0,7)]];for(let[c,l]of s){let a=new Set;for(let m of o){let E=l(new Date(m.pointInTime));if(a.has(E))continue;if(a.add(E),a.size<=Math.max(0,c??0))r.add(m.id)}}}return t.filter((n)=>!r.has(n.id))}coverage(e,t=this.now()){let r=new Map(this.listDestinations(e).map((n)=>[n.id,n]));return this.listPolicies(e).map((n)=>{let i=this.listRecoveryPoints(e,n.id).filter((c)=>c.status==="available"),o=i[0],s=o?(t.getTime()-new Date(o.pointInTime).getTime())/60000:Number.POSITIVE_INFINITY;return{policy:n,lastRecoveryPoint:o,missedRpo:n.enabled&&s>n.expectedRpoMinutes,unverified:i.filter((c)=>c.verificationState!=="verified").length,destinationHealthy:r.get(n.destinationId)?.status==="healthy"}})}}import{createCipheriv as nv,createDecipheriv as iv,createHash as Fg,randomBytes as Ug}from"node:crypto";var pu=Buffer.from("TSCB1"),cc=(e)=>`sha256:${Fg("sha256").update(e).digest("hex")}`;function zg(e){return Fg("sha256").update(e).digest()}function ov(e,t,r){let n=r?Buffer.from(r):Ug(12);if(n.length!==12)throw Error("Backup encryption IV must contain 12 bytes.");let i=nv("aes-256-gcm",zg(t),n),o=Buffer.concat([i.update(e),i.final()]),s=i.getAuthTag();return Buffer.concat([pu,n,s,o])}function sv(e,t){let r=Buffer.from(e);if(!r.subarray(0,pu.length).equals(pu))throw Error("Backup does not contain a valid encrypted envelope.");let n=r.subarray(5,17),i=r.subarray(17,33),o=r.subarray(33),s=iv("aes-256-gcm",zg(t),n);return s.setAuthTag(i),Buffer.concat([s.update(o),s.final()])}function av(e){let t;try{t=JSON.parse(e)}catch{throw Error("Backup destination credential must be a JSON object with accessKeyId and secretAccessKey.")}if(!t.accessKeyId||!t.secretAccessKey)throw Error("Backup destination credential requires accessKeyId and secretAccessKey.");if(t.expiresAt){let r=new Date(String(t.expiresAt));if(!Number.isFinite(r.getTime()))throw Error("Backup destination credential expiresAt must be an ISO timestamp.");if(r.getTime()<=Date.now())throw Error("Backup destination credential has expired.")}return{accessKeyId:String(t.accessKeyId),secretAccessKey:String(t.secretAccessKey),sessionToken:t.sessionToken?String(t.sessionToken):void 0}}async function Vg(e,t,r=new Date){if(!e.credentialRef)return{status:"default"};try{let n=JSON.parse(await t.resolve(e.credentialRef));if(!n.accessKeyId||!n.secretAccessKey)return{status:"invalid"};if(!n.expiresAt)return{status:"static"};let i=new Date(String(n.expiresAt));if(!Number.isFinite(i.getTime()))return{status:"invalid"};let o=i.getTime()-r.getTime();return{status:o<=0?"expired":o<=604800000?"expiring":"valid",expiresAt:i.toISOString()}}catch{return{status:"invalid"}}}class Mn{secrets;clientFactory;multipartThreshold;partSize;constructor(e,t=(i,o)=>new f(i.region??"us-east-1",void 0,{endpoint:i.endpoint?new URL(i.endpoint).host:void 0,forcePathStyle:i.forcePathStyle,credentials:o}),r=8388608,n=8388608){this.secrets=e;this.clientFactory=t;this.multipartThreshold=r;this.partSize=n}async client(e){let t=e.credentialRef?av(await this.secrets.resolve(e.credentialRef)):void 0;return this.clientFactory(e,t)}async test(e){if(!e.bucket)throw Error("S3 destination has no configured bucket.");let t=await this.client(e),r=`${e.prefix?`${e.prefix.replace(/\/$/,"")}/`:""}.ts-cloud-health/${crypto.randomUUID()}`;await t.putObject({bucket:e.bucket,key:r,body:"ts-cloud backup destination health check",contentType:"text/plain"});try{let n=await t.getObjectBytes(e.bucket,r);if(Buffer.from(n.body).toString()!=="ts-cloud backup destination health check")throw Error("Backup destination health object was corrupted.")}finally{await t.deleteObject(e.bucket,r)}}async upload(e,t){if(!e.bucket)throw Error("S3 destination has no configured bucket.");let r=await this.client(e),n=cc(t.body),i=e.encryption!=="provider"?await this.secrets.resolve(e.encryptionKeyRef):void 0,o=i?t.resume?.encryptionIv?Buffer.from(t.resume.encryptionIv,"base64url"):Ug(12):void 0,s=i?ov(t.body,i,o):Buffer.from(t.body),c=cc(s),l=`${e.prefix?`${e.prefix.replace(/\/$/,"")}/`:""}${t.key.replace(/^\/+/,"")}`,a=t.contentType??"application/octet-stream",m={"ts-cloud-format":"v1","ts-cloud-sha256":c.slice(7),"ts-cloud-encrypted":i?"true":"false"};if(t.resume&&t.resume.key!==l)throw Error("Multipart checkpoint does not match the requested backup key.");if(t.resume&&i&&!t.resume.encryptionIv)throw Error("Encrypted multipart checkpoint has no resumable envelope state.");if(t.resume&&i&&t.resume.plaintextChecksum!==n)throw Error("Encrypted multipart checkpoint does not match the backup payload.");if(s.length<this.multipartThreshold)await r.putObject({bucket:e.bucket,key:l,body:s,contentType:a,metadata:m});else{let E=t.resume?void 0:await r.createMultipartUpload(e.bucket,l,{contentType:a,metadata:m}),k=t.resume??{uploadId:E.UploadId,key:l,parts:[],bytesUploaded:0,encryptionIv:o?.toString("base64url"),plaintextChecksum:n},O=new Map(k.parts.map((G)=>[G.PartNumber,G])),q=Math.ceil(s.length/this.partSize);for(let G=0;G<q;G++){let Y=G+1;if(!O.has(Y)){let re=G*this.partSize,he=await r.uploadPart(e.bucket,l,k.uploadId,Y,s.subarray(re,Math.min(s.length,re+this.partSize)));O.set(Y,{PartNumber:Y,ETag:he.ETag})}k.parts=[...O.values()].sort((re,he)=>re.PartNumber-he.PartNumber),k.bytesUploaded=Math.min(s.length,Y*this.partSize),t.checkpoint?.(k)}await r.completeMultipartUpload(e.bucket,l,k.uploadId,k.parts)}return{uri:`s3://${e.bucket}/${l}`,key:l,sizeBytes:s.length,checksum:c,manifest:{format:"ts-cloud-backup-v1",encrypted:!!i,plaintextChecksum:n,storageChecksum:c,contentType:a}}}async download(e,t){if(!e.bucket)throw Error("S3 destination has no configured bucket.");let r=await this.client(e),n=await r.getObjectBytes(e.bucket,t.key),i=Buffer.from(n.body);if(cc(i)!==t.checksum)throw Error("Backup checksum verification failed; object is corrupt.");let o=t.manifest.encrypted?sv(i,await this.secrets.resolve(e.encryptionKeyRef)):i;if(cc(o)!==t.manifest.plaintextChecksum)throw Error("Backup plaintext checksum verification failed.");return o}async abortPartial(e,t){if(!e.bucket)throw Error("S3 destination has no configured bucket.");await(await this.client(e)).abortMultipartUpload(e.bucket,t.key,t.uploadId)}async delete(e,t){if(!e.bucket)throw Error("S3 destination has no configured bucket.");await(await this.client(e)).deleteObject(e.bucket,t)}}import{createHash as cv}from"node:crypto";var dv=(e)=>`sha256:${cv("sha256").update(e).digest("hex")}`;class Or{store;queue;now;constructor(e,t,r=()=>new Date){this.store=e;this.queue=t;this.now=r}enqueueBackup(e,t=this.now().toISOString(),r){if(!e.enabled)throw Error("Backup policy is disabled.");let n=this.store.createJob({projectId:e.projectId,policyId:e.id,kind:"backup",status:"queued",idempotencyKey:`backup:${e.id}:${t}`,target:{scheduledFor:t},cancellability:"checkpoint_only",progress:{phase:"queued"}});if(!n.operationId){let i=this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:r,kind:"backup.run",input:{backupJobId:n.id},lockKey:e.dataServiceId?`data-service:${e.dataServiceId}`:e.resourceId?`resource:${e.resourceId}`:`backup-policy:${e.id}`,providerKey:"backup",maxAttempts:3,timeoutSeconds:14400,retryClasses:["provider_transient"],resumePolicy:"requeue"});return this.store.updateJob(n.id,{operationId:i.operation.id})}return n}enqueueDue(e=this.now()){return this.store.duePolicies(e).map((t)=>{let r=t.nextRunAt;return this.store.advancePolicy(t.id,r),this.enqueueBackup(t,r)})}enqueueVerification(e){let t=this.store.createJob({projectId:e.projectId,policyId:e.policyId,recoveryPointId:e.id,kind:"verify",status:"queued",idempotencyKey:`verify:${e.id}:${e.checksum}`,target:{},cancellability:"safe",progress:{phase:"queued"}});if(!t.operationId){let r=this.queue.enqueue({projectId:e.projectId,resourceId:e.resourceId,kind:"backup.verify",input:{backupJobId:t.id},lockKey:`recovery-point:${e.id}`,providerKey:"backup",maxAttempts:2,timeoutSeconds:7200,retryClasses:["provider_transient"],resumePolicy:"requeue"});return this.store.updateJob(t.id,{operationId:r.operation.id})}return t}planRestore(e,t){if(e.status!=="available")throw Error("Only available recovery points can be restored.");if(e.verificationState!=="verified")throw Error("Restore requires a verified recovery point.");if(t.mode==="in_place"){if(!t.recentAuth)throw Error("In-place restore requires recent authentication.");if(t.confirm!==t.targetName)throw Error(`Type ${t.targetName} to confirm in-place restore.`);if(!t.downtimeAcknowledged)throw Error("In-place restore requires downtime acknowledgement.");let r=t.safetyBackupId?this.store.getRecoveryPoint(t.safetyBackupId):void 0;if(!r||r.id===e.id||r.status!=="available"||r.verificationState!=="verified"||r.resourceId!==e.resourceId||r.dataServiceId!==e.dataServiceId)throw Error("In-place restore requires a distinct verified safety backup for the same target.")}return{point:e,mode:t.mode,target:{...t.target,inPlace:t.mode==="in_place",restoreMode:t.mode},warnings:t.mode==="in_place"?["The target is locked against deployments and backup work.","Downtime and data replacement are expected.","Provider cancellation may stop only at a checkpoint."]:["An isolated target is created and health-validated before cleanup."]}}enqueueRestore(e,t){let r=this.planRestore(e,t),n=t.drill?"drill":"restore",i=dv(JSON.stringify({point:e.id,mode:t.mode,target:t.target,safety:t.safetyBackupId,drill:!!t.drill})),o=this.store.createJob({projectId:e.projectId,policyId:e.policyId,recoveryPointId:e.id,kind:n,status:"queued",idempotencyKey:`${n}:${i}`,target:r.target,restoreMode:r.mode,cancellability:"checkpoint_only",safetyBackupId:t.safetyBackupId,progress:{phase:"queued",warnings:r.warnings}});if(!o.operationId){let s=this.queue.enqueue({projectId:e.projectId,resourceId:e.resourceId,actorId:t.actorId,kind:t.drill?"backup.drill":"backup.restore",input:{backupJobId:o.id},lockKey:e.dataServiceId?`data-service:${e.dataServiceId}`:e.resourceId?`resource:${e.resourceId}`:`recovery-point:${e.id}`,providerKey:"backup",maxAttempts:1,timeoutSeconds:14400,retryClasses:[],resumePolicy:"fail"});return this.store.updateJob(o.id,{operationId:s.operation.id})}return o}enqueueRetention(e=this.now()){return this.store.retentionCandidates(e).map((t)=>{let r=this.store.createJob({projectId:t.projectId,policyId:t.policyId,recoveryPointId:t.id,kind:"cleanup",status:"queued",idempotencyKey:`cleanup:${t.id}:${t.expiresAt}`,target:{},cancellability:"safe",progress:{phase:"queued"}});if(!r.operationId){let n=this.queue.enqueue({projectId:t.projectId,resourceId:t.resourceId,kind:"backup.cleanup",input:{backupJobId:r.id},lockKey:`recovery-point:${t.id}`,providerKey:"backup",maxAttempts:3,timeoutSeconds:7200,retryClasses:["provider_transient"],resumePolicy:"requeue"});return this.store.updateJob(r.id,{operationId:n.operation.id})}return r})}}function qg(e){let t=e.now??(()=>new Date),r=new Or(e.store,e.queue,t),n=(c)=>{let l=c.recoveryPointId?e.store.getRecoveryPoint(c.recoveryPointId):void 0,a=c.policyId?e.store.getPolicy(c.policyId):l?.policyId?e.store.getPolicy(l.policyId):void 0;if(!a)throw Error("Backup policy was not found.");let m=e.store.getDestination(l?.destinationId??a.destinationId),E=e.resolveSource(a);if(!m)throw Error("Backup destination was not found.");if(!E)throw Error(`No ${a.resourceKind} backup adapter is configured.`);return{point:l,policy:a,destination:m,source:E}},i=(c)=>{let l=c.operation.input,a=e.store.getJob(String(l.backupJobId??""));if(!a)throw Error("Backup job was not found.");return e.store.updateJob(a.id,{status:"running",startedAt:a.startedAt??t().toISOString(),progress:{...a.progress,phase:"running"}}),a},o=(c,l)=>{let a=e.store.getJob(c.id)??c;e.store.updateJob(c.id,{status:"failed",finishedAt:t().toISOString(),error:l instanceof Error?l.message:String(l),progress:{...a.progress,phase:"failed"}})};return{"backup.run":async(c)=>{let l=i(c);try{let{policy:a,destination:m,source:E}=n(l),k=await E.create(a,c),O=e.resolveDestination(m),q=k.mode==="object"?await(async()=>{if(!O)throw Error("Backup destination adapter is not configured.");let he=e.store.getJob(l.id)?.progress,ee=he?.multipart,Re=ee&&typeof ee==="object"&&!Array.isArray(ee)&&typeof ee.uploadId==="string"&&typeof ee.key==="string"&&Array.isArray(ee.parts)?ee:void 0;return O.upload(m,{key:k.key,body:k.body,contentType:k.contentType,resume:Re,checkpoint:(at)=>{c.checkpoint("uploading",`Uploaded ${Number(at.bytesUploaded??0)} backup bytes.`),e.store.updateJob(l.id,{progress:{phase:"uploading",multipart:{...at}}})}})})():{uri:k.uri,key:k.uri,sizeBytes:k.sizeBytes,checksum:k.checksum,manifest:{format:"ts-cloud-backup-v1",encrypted:!1,plaintextChecksum:k.checksum,storageChecksum:k.checksum,contentType:"application/provider-snapshot"}},G=a.retention.expireAfterDays?new Date(t().getTime()+a.retention.expireAfterDays*86400000).toISOString():void 0,Y=e.store.getJob(l.id)?.startedAt,re=e.store.createRecoveryPoint({projectId:a.projectId,policyId:a.id,destinationId:m.id,resourceId:a.resourceId,dataServiceId:a.dataServiceId,backupJobId:l.id,kind:a.resourceKind,pointInTime:t().toISOString(),uri:q.uri,sizeBytes:q.sizeBytes,checksum:q.checksum,manifest:{...k.manifest,...q.manifest,storageKey:q.key},toolVersion:k.toolVersion,engineVersion:k.engineVersion,expiresAt:G,lockedUntil:m.immutability.defaultRetentionDays?new Date(t().getTime()+m.immutability.defaultRetentionDays*86400000).toISOString():void 0,held:!1,pinned:!1,status:"available",verificationState:"unverified",durationMs:Math.max(0,t().getTime()-new Date(Y??t().toISOString()).getTime())});if(k.mode==="external"&&m.provider==="aws_backup")e.store.recordDestinationTest(m.id,{ok:!0});return e.store.updateJob(l.id,{status:"succeeded",recoveryPointId:re.id,finishedAt:t().toISOString(),progress:{phase:"stored",recoveryPointId:re.id}}),r.enqueueVerification(re),{backupJobId:l.id,recoveryPointId:re.id}}catch(a){let m=e.store.getJob(l.id),E=m?.progress.multipart,k=(()=>{try{return n(l)}catch{return}})();if(k?.destination.provider==="aws_backup")e.store.recordDestinationTest(k.destination.id,{ok:!1,error:a instanceof Error?a.message:String(a)});let O=!1;if(E&&typeof E==="object"&&!Array.isArray(E)&&k){let q=e.resolveDestination(k.destination);if(O=!0,q?.abortPartial)try{await q.abortPartial(k.destination,E),O=!1,e.store.updateJob(l.id,{progress:{...m.progress,partialCleanup:"aborted"}})}catch{e.store.updateJob(l.id,{progress:{...m.progress,partialCleanup:"required"}})}}if(O)e.store.updateJob(l.id,{status:"cleanup_required",finishedAt:t().toISOString(),error:a instanceof Error?a.message:String(a),progress:{...e.store.getJob(l.id)?.progress??{},phase:"cleanup_required"}});else o(l,a);throw a}},"backup.verify":async(c)=>{let l=i(c);try{let{point:a,destination:m,source:E}=n(l);if(!a)throw Error("Recovery point was not found.");e.store.updateRecoveryPoint(a.id,{verificationState:"verifying"});let k;if(a.uri.startsWith("s3:")){let O=e.resolveDestination(m);if(!O)throw Error("Backup destination adapter is not configured.");let q=await O.download(m,{key:String(a.manifest.storageKey??""),checksum:a.checksum,manifest:a.manifest}),G=E.verify?await E.verify(a,q,c):{};k={bytes:q.length,checksum:a.checksum,...G}}else if(E.verifyExternal)k=await E.verifyExternal(a,c);else throw Error("External recovery point verification is not supported.");return e.store.updateRecoveryPoint(a.id,{verificationState:"verified",verifiedAt:t().toISOString(),manifest:{...a.manifest,verification:k}}),e.store.updateJob(l.id,{status:"succeeded",finishedAt:t().toISOString(),progress:{phase:"verified",evidence:k}}),{backupJobId:l.id,recoveryPointId:a.id,evidence:k}}catch(a){if(l.recoveryPointId)e.store.updateRecoveryPoint(l.recoveryPointId,{verificationState:/checksum|corrupt|authentic/i.test(a instanceof Error?a.message:String(a))?"corrupt":"failed"});throw o(l,a),a}},"backup.restore":async(c)=>s(c,!1),"backup.drill":async(c)=>s(c,!0),"backup.cleanup":async(c)=>{let l=i(c);try{let{point:a,destination:m,source:E}=n(l);if(!a)throw Error("Recovery point was not found.");if(!e.store.retentionCandidates(t()).some((k)=>k.id===a.id))throw Error("Recovery point is held, pinned, locked, or in active use.");if(e.store.updateRecoveryPoint(a.id,{status:"deleting"}),a.uri.startsWith("s3:")){let k=e.resolveDestination(m);if(!k)throw Error("Destination cleanup is unavailable.");await k.delete(m,String(a.manifest.storageKey??""))}else if(E.deleteExternal)await E.deleteExternal(a,c);else throw Error("External recovery point cleanup is unavailable.");return e.store.updateRecoveryPoint(a.id,{status:"deleted"}),e.store.updateJob(l.id,{status:"succeeded",finishedAt:t().toISOString(),progress:{phase:"deleted"}}),{backupJobId:l.id,recoveryPointId:a.id,deleted:!0}}catch(a){throw o(l,a),a}}};async function s(c,l){let a=i(c);try{let{point:m,policy:E,destination:k,source:O}=n(a);if(!m)throw Error("Recovery point was not found.");if(l&&!O.cleanup)throw Error("This backup source cannot safely clean a recovery drill target.");let q=m.uri.startsWith("s3:")?e.resolveDestination(k):void 0,G=q?await q.download(k,{key:String(m.manifest.storageKey??""),checksum:m.checksum,manifest:m.manifest}):void 0,Y=await O.restore(m,G,a.target,c),re=O.validateHealth?await O.validateHealth({...a.target,...Y},c):{healthy:!0,mode:"adapter"},he=e.validateHealth?await e.validateHealth(E,a.target):{healthy:!0,mode:"not_configured"},ee={...re,healthy:re.healthy===!0&&he.healthy===!0,configured:he};if(ee.healthy!==!0)throw Error("Restored target did not pass its configured health check.");if(l&&O.cleanup)await O.cleanup({...a.target,provider:m.manifest.provider??null},c);return e.store.updateJob(a.id,{status:"succeeded",finishedAt:t().toISOString(),healthResult:ee,progress:{phase:l?"drill_cleaned":"restored",restored:Y}}),{backupJobId:a.id,recoveryPointId:m.id,restored:Y,health:ee,cleaned:l}}catch(m){let E=(()=>{try{return n(a)}catch{return}})(),k=m instanceof Error?m.message:String(m),O=!1;if(l&&E?.source.cleanup)try{await E.source.cleanup({...a.target,provider:E.point?.manifest.provider??null},c)}catch{O=!0}if(O)e.store.updateJob(a.id,{status:"cleanup_required",finishedAt:t().toISOString(),error:k,progress:{...a.progress,phase:"cleanup_required"}});else o(a,m);throw m}}}import{createHash as uv}from"node:crypto";var lv=(e)=>`sha256:${uv("sha256").update(e).digest("hex")}`;class gu{dataServices;client;constructor(e,t=new le){this.dataServices=e;this.client=t}service(e){let t=e.dataServiceId?this.dataServices.get(e.dataServiceId):void 0;if(!t||!["aws_rds","aws_aurora"].includes(t.provider))throw Error("Managed database backup policy requires an RDS or Aurora data service.");return t}async waitForSnapshot(e,t,r){for(;;){r.throwIfCancellationRequested?.(),r.heartbeat?.();let n=e==="aws_aurora"?(await this.client.describeDBClusterSnapshots({DBClusterSnapshotIdentifier:t})).DBClusterSnapshots[0]:(await this.client.describeDBSnapshots({DBSnapshotIdentifier:t})).DBSnapshots?.[0];if(!n)throw Error("Provider snapshot was not found.");let i=n,o=String(i.Status??i.DBSnapshotStatus??"unknown");if(r.checkpoint?.("provider_snapshot",`Database snapshot ${t} is ${o}.`),o==="available")return i;if(["deleted","deleting","failed"].includes(o))throw Error(`Provider snapshot ${t} failed with state ${o}.`);await Bun.sleep(5000)}}async create(e,t){let r=this.service(e),n=String(t.operation?.id??new Date().toISOString()).replace(/[^A-Za-z0-9]/g,"").slice(0,20),i=`${r.placement.slice(0,42).replace(/-+$/,"")}-${n}`;if(r.provider==="aws_aurora")await this.client.createDBClusterSnapshot(r.placement,i);else await this.client.createDBSnapshot({DBInstanceIdentifier:r.placement,DBSnapshotIdentifier:i});await this.waitForSnapshot(r.provider,i,t);let o=`${r.provider}:${r.placement}:${i}`;return{mode:"external",uri:`aws-backup:${o}`,checksum:lv(o),sizeBytes:0,manifest:{provider:r.provider,sourceId:r.placement,snapshotId:i,plan:r.plan,engine:r.engine},engineVersion:r.engineVersion,toolVersion:"aws-rds-api-2014-10-31"}}async verifyExternal(e,t){let r=String(e.manifest.snapshotId??""),n=String(e.manifest.provider??"");if(!r)throw Error("Snapshot recovery point has no snapshot ID.");let i=await this.waitForSnapshot(n,r,t),o=String(i.Status??i.DBSnapshotStatus??"unknown");return{snapshotId:r,status:o,encrypted:i.Encrypted??i.StorageEncrypted??!0}}async restore(e,t,r,n){let i=String(r.targetId??""),o=String(e.manifest.snapshotId??""),s=String(e.manifest.provider??"");if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(i))throw Error("Managed restore requires a valid distinct targetId.");if(i===e.manifest.sourceId)throw Error("Managed restore target must differ from its source.");if(s==="aws_aurora"){let c=e.manifest.engine==="postgres"?"aurora-postgresql":"aurora-mysql";await this.client.restoreDBClusterFromSnapshot({DBClusterIdentifier:i,SnapshotIdentifier:o,Engine:c,EngineVersion:e.engineVersion,DeletionProtection:!0,ServerlessV2ScalingConfiguration:{MinCapacity:Number(r.minCapacity)||0.5,MaxCapacity:Number(r.maxCapacity)||4}}),await this.client.createDBInstance({DBInstanceIdentifier:`${i}-writer-1`,DBClusterIdentifier:i,DBInstanceClass:String(r.plan??e.manifest.plan??"db.serverless"),Engine:c,PubliclyAccessible:!1})}else await this.client.restoreDBInstanceFromDBSnapshot({DBInstanceIdentifier:i,DBSnapshotIdentifier:o,DBInstanceClass:String(r.plan??e.manifest.plan??""),PubliclyAccessible:!1,DeletionProtection:!0,Tags:[{Key:"managed-by",Value:"ts-cloud-restore"}]});return{targetId:i,provider:s,status:"creating",isolated:!0}}async validateHealth(e,t){let r=String(e.targetId??""),n=String(e.provider??"");for(;;){t.throwIfCancellationRequested?.(),t.heartbeat?.();let i=n==="aws_aurora"?(await this.client.describeDBClusters({DBClusterIdentifier:r})).DBClusters?.[0]:(await this.client.describeDBInstances({DBInstanceIdentifier:r})).DBInstances?.[0];if(!i)throw Error("Restored managed database was not found.");let o=String(i.Status??i.DBInstanceStatus??"unknown");if(t.checkpoint?.("provider_restore",`Restored database ${r} is ${o}.`),o==="available")return{healthy:!0,targetId:r,provider:n,status:o};if(["deleted","deleting","failed","incompatible-restore"].includes(o))throw Error(`Restored managed database ${r} failed with state ${o}.`);await Bun.sleep(5000)}}async cleanup(e,t){let r=String(e.targetId??""),n=String(e.provider??"");if(!r)throw Error("Restore cleanup target is required.");if(n==="aws_aurora")await this.client.deleteDBInstance({DBInstanceIdentifier:`${r}-writer-1`,SkipFinalSnapshot:!0}),await this.client.modifyDBCluster({DBClusterIdentifier:r,DeletionProtection:!1,ApplyImmediately:!0}),await this.client.deleteDBCluster(r);else await this.client.modifyDBInstance({DBInstanceIdentifier:r,DeletionProtection:!1,ApplyImmediately:!0}),await this.client.deleteDBInstance({DBInstanceIdentifier:r,SkipFinalSnapshot:!0,DeleteAutomatedBackups:!0})}async deleteExternal(e,t){let r=String(e.manifest.snapshotId??"");if(e.manifest.provider==="aws_aurora")await this.client.deleteDBClusterSnapshot(r);else await this.client.deleteDBSnapshot(r)}}var en=(e,t="none",r=!1)=>({supported:!0,downtime:t,destructive:r,explanation:e}),jr=(e)=>({supported:!1,downtime:"none",destructive:!1,explanation:e});function qt(e,t){let r=["aws_rds","aws_aurora","aws_elasticache"].includes(t),n=["server","container"].includes(t),i=["postgres","mysql","mariadb"].includes(e),o=e==="redis",s={};return s.create=t==="external"?jr("External services can be adopted as read-only inventory."):en(r?"Provision through the provider API.":"Provision through the owning runtime driver.","possible"),s.observe=t==="external"?jr("External observation requires a configured provider adapter."):en("Provider/runtime health and endpoint metadata are observable."),s.connect=en("Connection guidance uses secret references and never returns a password by default."),s.backup=i&&(r||n)?en(r?"Create a provider snapshot.":"Create a consistent engine-native dump.","possible"):jr("This cache path is not a durable backup source."),s.restore=r&&i?en("Restore creates a reviewed provider target.","required",!0):jr("Restore requires a configured provider restore runner."),s.restart=t==="external"?jr("External restart requires a configured provider adapter."):en(r?"Provider restart/failover semantics apply.":"Restart the owning service unit.","required"),s.resize=t==="aws_elasticache"?jr("ElastiCache resizing requires a replication-group migration runner."):r?en("Provider plan/storage modification may enter a maintenance window.","possible"):n?en("Edit host/container resources and reconcile.","required"):jr("External resize requires a configured provider adapter."),s.version=n?jr("Runtime version upgrades require an explicit image migration runner."):r&&t!=="aws_elasticache"?en(i?"Major versions require compatibility preflight and backup.":"Engine upgrades require a maintenance window.","required"):jr("External upgrades require a configured provider adapter."),s.rotate=t==="aws_elasticache"||t==="external"||n&&!i&&!o?jr("Credential rotation is not available for this provider/engine path."):en("Rotate through the secret backend, update the engine, then flag dependent releases."),s.expose=n?jr("Direct container publishing is refused; use a reviewed firewall and proxy policy."):t==="aws_rds"?en("Exposure is reconciled through security groups; public access defaults off."):jr("Exposure changes require a provider-specific network runner."),s.delete=t==="external"?jr("External deletion requires a configured provider adapter."):en(r?"Final snapshot is supported where the provider allows it.":"A final engine backup is required unless explicitly retained.","required",!0),s.logs=n?en("Read bounded service logs from the runtime."):jr("Provider log export is not configured for this adapter."),s.slow_queries=n&&i?en("Read bounded runtime logs after engine slow-query logging is enabled."):jr("A slow-query log runner is not configured for this provider."),s.users=n&&i?en("Logical users can be listed; creation requires a referenced secondary credential."):jr("User management requires an engine connection runner."),s.databases=n&&i?en("Logical databases can be listed, created, and confirmation-gated for deletion."):jr("Logical database management requires an engine connection runner."),{actions:s,endpointTypes:r?["internal","external","tunnel"]:["internal","tunnel"],metrics:o?["connections","memory","evictions","hit_rate","latency"]:["connections","cpu","storage","read_latency","write_latency","iops"]}}var Os=(e)=>e==null?void 0:String(e),uc=(e)=>Number(e)===1,dc=(e)=>{try{return JSON.parse(String(e))}catch{return{}}};function Jg(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:Os(e.environment_id),resourceId:Os(e.resource_id),name:String(e.name),engine:String(e.engine),provider:String(e.provider),placement:String(e.placement),engineVersion:Os(e.engine_version),plan:String(e.plan),storageGb:e.storage_gb==null?void 0:Number(e.storage_gb),highAvailability:uc(e.high_availability),publicExposure:uc(e.public_exposure),allowedCidrs:dc(e.allowed_cidrs),desiredState:dc(e.desired_state),observedState:dc(e.observed_state),capabilities:dc(e.capabilities),credentialRef:Os(e.credential_ref),status:String(e.status),origin:String(e.origin),managementEnabled:uc(e.management_enabled),ownerActorId:Os(e.owner_actor_id),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class Ht{controlPlane;now;constructor(e,t=()=>new Date){this.controlPlane=e;this.now=t}create(e){if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.name))throw Error("Data service names must be 2-63 lowercase letters, numbers, or dashes.");if(e.publicExposure&&(!e.allowedCidrs.length||e.allowedCidrs.includes("0.0.0.0/0")))throw Error("Public exposure requires explicit narrow CIDRs; 0.0.0.0/0 is refused.");let t=crypto.randomUUID(),r=this.now().toISOString(),n=qt(e.engine,e.provider);return this.controlPlane.database.run("INSERT INTO data_services (id,organization_id,project_id,environment_id,resource_id,name,engine,provider,placement,engine_version,plan,storage_gb,high_availability,public_exposure,allowed_cidrs,desired_state,observed_state,capabilities,credential_ref,status,origin,management_enabled,owner_actor_id,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.name,e.engine,e.provider,e.placement,e.engineVersion??null,e.plan,e.storageGb??null,e.highAvailability?1:0,e.publicExposure?1:0,JSON.stringify(e.allowedCidrs),JSON.stringify(e.desiredState),JSON.stringify(e.observedState),JSON.stringify(n),e.credentialRef??null,e.status,e.origin,e.managementEnabled?1:0,e.ownerActorId??null,1,r,r]),this.get(t)}get(e){let t=this.controlPlane.database.query("SELECT * FROM data_services WHERE id=?").get(e);return t?Jg(t):void 0}list(e,t){return this.controlPlane.database.query(`SELECT * FROM data_services WHERE project_id=?${t?" AND environment_id=?":""} ORDER BY name`).all(e,...t?[t]:[]).map(Jg)}update(e,t,r){let n=this.get(e);if(!n)throw Error("Data service was not found.");if(n.version!==t)throw Error("Data service changed; refresh before retrying.");let i={...n,...r};if(i.publicExposure&&(!i.allowedCidrs.length||i.allowedCidrs.includes("0.0.0.0/0")))throw Error("Public exposure requires explicit narrow CIDRs; 0.0.0.0/0 is refused.");if(this.controlPlane.database.run("UPDATE data_services SET plan=?,storage_gb=?,engine_version=?,high_availability=?,public_exposure=?,allowed_cidrs=?,desired_state=?,observed_state=?,status=?,management_enabled=?,credential_ref=?,version=version+1,updated_at=? WHERE id=? AND version=?",[i.plan,i.storageGb??null,i.engineVersion??null,i.highAvailability?1:0,i.publicExposure?1:0,JSON.stringify(i.allowedCidrs),JSON.stringify(i.desiredState),JSON.stringify(i.observedState),i.status,i.managementEnabled?1:0,i.credentialRef??null,this.now().toISOString(),e,t]).changes!==1)throw Error("Data service changed; refresh before retrying.");return this.get(e)}credential(e){let t=this.controlPlane.database.query("SELECT * FROM data_service_credentials WHERE service_id=? ORDER BY version DESC LIMIT 1").get(e);return t?{id:String(t.id),serviceId:String(t.service_id),username:String(t.username),secretRef:String(t.secret_ref),version:Number(t.version),createdAt:String(t.created_at),rotatedAt:Os(t.rotated_at)}:void 0}saveCredential(e,t,r){let n=this.credential(e),i=n?.id??crypto.randomUUID(),o=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO data_service_credentials (id,service_id,username,secret_ref,version,created_at,rotated_at) VALUES (?,?,?,?,?,?,?) ON CONFLICT(service_id,username) DO UPDATE SET secret_ref=excluded.secret_ref,version=data_service_credentials.version+1,rotated_at=excluded.rotated_at",[i,e,t,r,n?.version??1,n?.createdAt??o,n?o:null]),this.credential(e)}addDependency(e){let t=this.now().toISOString();return this.controlPlane.database.run("INSERT INTO data_service_dependencies (service_id,resource_id,secret_ref,requires_redeploy,created_at) VALUES (?,?,?,?,?) ON CONFLICT(service_id,resource_id) DO UPDATE SET secret_ref=excluded.secret_ref,requires_redeploy=excluded.requires_redeploy",[e.serviceId,e.resourceId,e.secretRef,e.requiresRedeploy?1:0,t]),{...e,createdAt:t}}dependencies(e){return this.controlPlane.database.query("SELECT * FROM data_service_dependencies WHERE service_id=? ORDER BY resource_id").all(e).map((t)=>({serviceId:String(t.service_id),resourceId:String(t.resource_id),secretRef:String(t.secret_ref),requiresRedeploy:uc(t.requires_redeploy),createdAt:String(t.created_at)}))}removeDependency(e,t){return this.controlPlane.database.run("DELETE FROM data_service_dependencies WHERE service_id=? AND resource_id=?",[e,t]).changes===1}remove(e){this.controlPlane.database.run("DELETE FROM data_services WHERE id=?",[e])}}function Wg(){let t=crypto.getRandomValues(new Uint8Array(40));return Array.from(t,(r)=>"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^&*_-+="[r%69]).join("")}function bn(e,t){return t.map((r)=>{let n=r.type==="tunnel"?"127.0.0.1":r.host,i=e.engine==="redis"?`redis-cli -h ${n} -p ${r.port}${r.tls?" --tls":""}`:e.engine==="postgres"?`psql "host=${n} port=${r.port} dbname=${r.database??"postgres"} sslmode=${r.tls?"require":"disable"}"`:e.engine==="mongodb"?`mongosh "mongodb://${n}:${r.port}/${r.database??"admin"}${r.tls?"?tls=true":""}"`:e.engine==="libsql"?`turso db shell ${r.tls?"https":"http"}://${n}:${r.port}`:`mysql --host=${n} --port=${r.port} --database=${r.database??"mysql"} --ssl-mode=${r.tls?"REQUIRED":"DISABLED"}`;return{type:r.type,command:i,secretRef:e.credentialRef}})}class Rr{store;queue;secrets;constructor(e,t,r){this.store=e;this.queue=t;this.secrets=r}async create(e){let t,r;if(e.provider!=="aws_elasticache"){let n=e.username??"app",i=Wg();r=`secret://data-services/${e.projectId}/${e.name}/${n}`,await this.secrets.put(r,i),t={username:n,password:i,secretRef:r}}try{let n=this.store.create({...e,credentialRef:r,status:"planning"});if(t)this.store.saveCredential(n.id,t.username,t.secretRef);let i=this.enqueue(n,"create",{});return{service:n,credential:t,operationId:i}}catch(n){if(r)await this.secrets.remove(r);throw n}}plan(e,t,r={}){let n=e.capabilities.actions[t],i=t==="version"&&String(r.engineVersion??"").split(".")[0]!==String(e.engineVersion??"").split(".")[0];return{service:e,action:t,capability:n,changes:r,preflight:{backupRequired:["delete","restore"].includes(t)||i,compatibilityRequired:i,typedConfirmation:n.destructive?e.name:void 0,retentionChoiceRequired:t==="delete"},warnings:[...n.downtime!=="none"?[`Downtime is ${n.downtime}.`]:[],...e.origin==="adopted"&&!e.managementEnabled?["Adopted resource is read-only until management is explicitly enabled."]:[]]}}enqueue(e,t,r,n){let i=this.plan(e,t,r);if(!i.capability.supported)throw Error(i.capability.explanation);if(e.origin==="adopted"&&!e.managementEnabled&&t!=="observe")throw Error("Adopted resources remain read-only until management is explicitly enabled.");if(i.preflight.typedConfirmation&&r.confirm!==i.preflight.typedConfirmation)throw Error(`Type ${i.preflight.typedConfirmation} to confirm ${t}.`);if(i.preflight.retentionChoiceRequired&&!["final_backup","retain"].includes(String(r.retention??"")))throw Error("Deletion requires retention final_backup or retain.");if(i.preflight.compatibilityRequired&&(r.compatibilityReviewed!==!0||!r.backupId))throw Error("Major version changes require compatibilityReviewed=true and a backupId.");if(t==="restore"){let o=String(r.backupId??""),s=String(r.targetId??"");if(!o||!s)throw Error("Restore requires both backupId and targetId.");if(s===e.placement)throw Error("Restore targetId must differ from the source placement.");if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(s))throw Error("Restore targetId must be 2-63 lowercase letters, numbers, or dashes.")}return this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:n,kind:"data_service.action",input:{serviceId:e.id,action:t,...r},lockKey:`data-service:${e.id}`,providerKey:e.provider,maxAttempts:3,timeoutSeconds:7200,retryClasses:["provider_transient"],resumePolicy:"requeue"}).operation.id}async rotate(e,t,r){let n=this.store.credential(e.id);if(!n)throw Error("Data service credential metadata was not found.");let i=Wg(),o=`${n.secretRef}/v${n.version+1}`;await this.secrets.put(o,i);try{return await t.action(e,"rotate",{username:n.username,secretRef:o},i,r),this.store.saveCredential(e.id,n.username,o),this.store.update(e.id,e.version,{credentialRef:o}),{credential:{username:n.username,password:i,secretRef:o},dependencies:this.store.dependencies(e.id).filter((s)=>s.requiresRedeploy).map((s)=>s.resourceId)}}catch(s){throw await this.secrets.remove(o),s}}}function Hg(e){return{"data_service.action":async(t)=>{let r=t.operation.input,n=e.store.get(String(r.serviceId??"")),i=String(r.action??"");if(!n)throw Error("Data service was not found.");let o=e.resolveAdapter(n);if(!o||o.provider!==n.provider||!o.engines.includes(n.engine))throw Error(`No ${n.provider}/${n.engine} adapter is configured.`);if(i==="rotate"){let c=await new Rr(e.store,new b(e.store.controlPlane),e.secrets).rotate(n,o,t);return{serviceId:n.id,action:i,username:c.credential.username,secretRef:c.credential.secretRef,dependencies:c.dependencies}}let s=n.credentialRef?await e.secrets.resolve(n.credentialRef):void 0;try{let c=i==="observe"?await o.observe(n):i==="create"?await o.apply(n,s,t):await o.action(n,i,r,s,t),l=e.store.get(n.id);return e.store.update(n.id,l.version,{observedState:c,status:i==="delete"?r.retention==="retain"?"retained":"deleting":"available"}),{serviceId:n.id,action:i,observed:c}}catch(c){let l=e.store.get(n.id);if(e.store.update(n.id,l.version,{status:"failed",observedState:{...l.observedState,error:c instanceof Error?c.message:String(c)}}),/temporar|timeout|unavailable|throttl/i.test(c instanceof Error?c.message:String(c)))throw new _e(c instanceof Error?c.message:String(c),"provider_transient");throw c}}}}class _s{transport;constructor(e){this.transport=e}observe(e){return this.transport.observe(e.placement)}apply(e,t){return this.transport.apply({id:e.placement,name:e.name,engine:e.engine,engineVersion:e.engineVersion??null,plan:e.plan,storageGb:e.storageGb??null,highAvailability:e.highAvailability,publicExposure:e.publicExposure,allowedCidrs:e.allowedCidrs,username:e.desiredState.username??"app",desiredState:e.desiredState},t)}action(e,t,r,n,i){return this.transport.execute(e.placement,t,{engine:e.engine,engineVersion:e.engineVersion??null,plan:e.plan,desiredState:e.desiredState,...r},n,i)}}class vn extends _s{provider="aws_rds";engines=["postgres","mysql","mariadb"]}class Tn extends _s{provider="aws_aurora";engines=["postgres","mysql"]}class En extends _s{provider="aws_elasticache";engines=["redis"]}class wn extends _s{provider="server";engines=["postgres","mysql","mariadb","redis","mongodb","libsql"]}class Cn extends _s{provider="container";engines=["postgres","mysql","mariadb","redis","mongodb","libsql"]}var gc=(e,t)=>{let r=e.desiredState;return e[t]??(r&&typeof r==="object"&&!Array.isArray(r)?r[t]:void 0)},Ft=(e,t,r)=>{let n=gc(e,t);return n==null?r:String(n)},Gn=(e,t)=>{let r=gc(e,t);return r==null?void 0:Number(r)},Ao=(e,t)=>{let r=gc(e,t);return r==null?void 0:r===!0||r==="true"},Ns=(e,t)=>{let r=gc(e,t);return Array.isArray(r)?r.map(String):[]},pc=(e,t)=>Ft(t,"snapshotId")??`${e}-final-${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}`;function lc(e){if(!e)throw Error("RDS instance was not found.");return{providerId:e.DBInstanceIdentifier??null,status:e.DBInstanceStatus??"unknown",engine:e.Engine??null,engineVersion:e.EngineVersion??null,plan:e.DBInstanceClass??null,storageGb:e.AllocatedStorage??null,highAvailability:e.MultiAZ??!1,publicExposure:e.PubliclyAccessible??!1,endpoint:e.Endpoint?.Address??null,port:e.Endpoint?.Port??null,username:e.MasterUsername??null,database:e.DBName??null,encrypted:e.StorageEncrypted??!1}}class An{client;constructor(e=new le){this.client=e}async observe(e){return lc(await this.client.describeDBInstance(e))}async apply(e,t){let r=String(e.id),n=await this.client.createDBInstance({DBInstanceIdentifier:r,DBInstanceClass:String(e.plan),Engine:String(e.engine),MasterUsername:Ft(e,"username","app"),MasterUserPassword:t,DBName:Ft(e,"database"),AllocatedStorage:Gn(e,"storageGb"),VpcSecurityGroupIds:Ns(e,"securityGroupIds"),DBSubnetGroupName:Ft(e,"subnetGroup"),BackupRetentionPeriod:Gn(e,"backupRetentionDays")??7,MultiAZ:Ao(e,"highAvailability"),EngineVersion:Ft(e,"engineVersion"),PubliclyAccessible:Ao(e,"publicExposure")??!1,StorageType:Ft(e,"storageType","gp3"),StorageEncrypted:!0,KmsKeyId:Ft(e,"kmsKeyId"),DeletionProtection:!0,Tags:[{Key:"managed-by",Value:"ts-cloud"}]});return lc(n.DBInstance)}async execute(e,t,r,n,i){if(t==="observe")return this.observe(e);if(t==="restart")return await this.client.rebootDBInstance({DBInstanceIdentifier:e}),{status:"rebooting"};if(t==="backup"){let o=pc(e,r);return await this.client.createDBSnapshot({DBInstanceIdentifier:e,DBSnapshotIdentifier:o}),{status:"snapshotting",snapshotId:o}}if(t==="restore"){let o=String(r.targetId),s=await this.client.restoreDBInstanceFromDBSnapshot({DBInstanceIdentifier:o,DBSnapshotIdentifier:String(r.backupId),DBInstanceClass:Ft(r,"plan"),DBSubnetGroupName:Ft(r,"subnetGroup"),MultiAZ:Ao(r,"highAvailability"),PubliclyAccessible:!1,StorageType:Ft(r,"storageType"),VpcSecurityGroupIds:Ns(r,"securityGroupIds"),DeletionProtection:!0,Tags:[{Key:"managed-by",Value:"ts-cloud"}]});return{...lc(s.DBInstance),sourceId:e,restoreTargetId:o}}if(t==="delete"){if(r.retention==="retain")return{status:"retained"};let o=pc(e,r);return await this.client.modifyDBInstance({DBInstanceIdentifier:e,DeletionProtection:!1,ApplyImmediately:!0}),await this.client.deleteDBInstance({DBInstanceIdentifier:e,SkipFinalSnapshot:!1,FinalDBSnapshotIdentifier:o,DeleteAutomatedBackups:!1}),{status:"deleting",finalSnapshotId:o}}if(["resize","version","rotate","expose"].includes(t)){let o=await this.client.modifyDBInstance({DBInstanceIdentifier:e,DBInstanceClass:Ft(r,"plan"),AllocatedStorage:Gn(r,"storageGb"),MasterUserPassword:t==="rotate"?n:void 0,EngineVersion:Ft(r,"engineVersion"),MultiAZ:Ao(r,"highAvailability"),PubliclyAccessible:Ao(r,"publicExposure"),VpcSecurityGroupIds:Ns(r,"securityGroupIds"),ApplyImmediately:Ao(r,"applyImmediately")??!0});return lc(o.DBInstance)}throw Error(`RDS action ${t} requires an engine connection runner.`)}}function mu(e){if(!e)throw Error("Aurora cluster was not found.");return{providerId:e.DBClusterIdentifier??null,status:e.Status??"unknown",engine:e.Engine??null,engineVersion:e.EngineVersion??null,endpoint:e.Endpoint??null,readerEndpoint:e.ReaderEndpoint??null,port:e.Port??null,username:e.MasterUsername??null,database:e.DatabaseName??null,encrypted:e.StorageEncrypted??!1,highAvailability:e.MultiAZ??!0}}class In{client;constructor(e=new le){this.client=e}async observe(e){let t=await this.client.describeDBClusters({DBClusterIdentifier:e});return mu(t.DBClusters?.[0])}async apply(e,t){let r=String(e.id),n=String(e.engine)==="postgres"?"aurora-postgresql":"aurora-mysql";return await this.client.createDBCluster({DBClusterIdentifier:r,Engine:n,EngineVersion:Ft(e,"engineVersion"),MasterUsername:Ft(e,"username","app"),MasterUserPassword:t,DatabaseName:Ft(e,"database"),DBSubnetGroupName:Ft(e,"subnetGroup"),VpcSecurityGroupIds:Ns(e,"securityGroupIds"),BackupRetentionPeriod:Gn(e,"backupRetentionDays")??7,StorageEncrypted:!0,KmsKeyId:Ft(e,"kmsKeyId"),DeletionProtection:!0,ServerlessV2ScalingConfiguration:{MinCapacity:Gn(e,"minCapacity")??0.5,MaxCapacity:Gn(e,"maxCapacity")??4}}),await this.client.createDBInstance({DBInstanceIdentifier:`${r}-writer-1`,DBClusterIdentifier:r,DBInstanceClass:String(e.plan||"db.serverless"),Engine:n,PubliclyAccessible:Ao(e,"publicExposure")??!1}),{status:"creating",providerId:r}}async execute(e,t,r,n){if(t==="observe")return this.observe(e);if(t==="restart")return await this.client.rebootDBCluster(e),{status:"rebooting"};if(t==="backup"){let i=pc(e,r);return await this.client.createDBClusterSnapshot(e,i),{status:"snapshotting",snapshotId:i}}if(t==="restore"){let i=String(r.targetId),o=String(r.engine)==="postgres"?"aurora-postgresql":"aurora-mysql",s=await this.client.restoreDBClusterFromSnapshot({DBClusterIdentifier:i,SnapshotIdentifier:String(r.backupId),Engine:o,EngineVersion:Ft(r,"engineVersion"),DBSubnetGroupName:Ft(r,"subnetGroup"),VpcSecurityGroupIds:Ns(r,"securityGroupIds"),DeletionProtection:!0,ServerlessV2ScalingConfiguration:{MinCapacity:Gn(r,"minCapacity")??0.5,MaxCapacity:Gn(r,"maxCapacity")??4}});return await this.client.createDBInstance({DBInstanceIdentifier:`${i}-writer-1`,DBClusterIdentifier:i,DBInstanceClass:Ft(r,"plan","db.serverless"),Engine:o,PubliclyAccessible:!1}),{...mu(s.DBCluster),sourceId:e,restoreTargetId:i}}if(t==="delete"){if(r.retention==="retain")return{status:"retained"};let i=pc(e,r);return await this.client.modifyDBCluster({DBClusterIdentifier:e,DeletionProtection:!1,ApplyImmediately:!0}),await this.client.deleteDBCluster(e,i),{status:"deleting",finalSnapshotId:i}}if(["resize","version","rotate"].includes(t)){let i=await this.client.modifyDBCluster({DBClusterIdentifier:e,ServerlessV2ScalingConfiguration:Gn(r,"minCapacity")==null&&Gn(r,"maxCapacity")==null?void 0:{MinCapacity:Gn(r,"minCapacity")??0.5,MaxCapacity:Gn(r,"maxCapacity")??4},EngineVersion:Ft(r,"engineVersion"),MasterUserPassword:t==="rotate"?n:void 0,ApplyImmediately:Ao(r,"applyImmediately")??!0});return mu(i.DBCluster)}throw Error(`Aurora action ${t} requires an engine connection runner.`)}}class Rn{client;constructor(e=new te){this.client=e}async observe(e){let t=(await this.client.describeCacheClusters(e)).CacheClusters[0];if(!t)throw Error("ElastiCache cluster was not found.");let r=t.CacheNodes?.[0]?.Endpoint;return{providerId:t.CacheClusterId,status:t.CacheClusterStatus,engine:t.Engine,engineVersion:t.EngineVersion,plan:t.CacheNodeType,nodes:t.NumCacheNodes,endpoint:r?.Address??null,port:r?.Port??null}}async apply(e){let t=await this.client.createCacheCluster({cacheClusterId:String(e.id),engine:"redis",cacheNodeType:String(e.plan),numCacheNodes:Gn(e,"nodes")??1,engineVersion:Ft(e,"engineVersion"),port:Gn(e,"port"),securityGroupIds:Ns(e,"securityGroupIds"),subnetGroupName:Ft(e,"subnetGroup"),tags:[{Key:"managed-by",Value:"ts-cloud"}]});return{providerId:t.CacheCluster.CacheClusterId,status:t.CacheCluster.CacheClusterStatus}}async execute(e,t,r){if(t==="observe")return this.observe(e);if(t==="restart"){let n=(await this.client.describeCacheClusters(e)).CacheClusters[0];return await this.client.rebootCacheCluster(e,n?.CacheNodes?.map((i)=>i.CacheNodeId)??["0001"]),{status:"rebooting"}}if(t==="delete"){if(r.retention==="retain")return{status:"retained"};return await this.client.deleteCacheCluster(e),{status:"deleting"}}throw Error(`ElastiCache action ${t} is not supported by this cluster mode.`)}}import{mkdir as pv,writeFile as gv}from"node:fs/promises";import{join as mv}from"node:path";async function Zn(e,t,r=!1){let n=Bun.spawn(["docker",...e],{stdin:t==null?"ignore":"pipe",stdout:"pipe",stderr:"pipe"}),i=new Response(n.stdout).text(),o=new Response(n.stderr).text();if(t!=null)n.stdin.write(t),n.stdin.end();let[s,c,l]=await Promise.all([n.exited,i,o]);if(s!==0&&!r)throw Error(`Docker command failed (${s}): ${l.trim()||c.trim()}`);return{code:s,stdout:c,stderr:l}}class Gg{async ensureNetwork(e){if((await Zn(["network","inspect",e],void 0,!0)).code!==0)await Zn(["network","create","--internal",e])}async seedSecret(e,t){await Zn(["volume","create",e]),await Zn(["run","--rm","-i","-v",`${e}:/run/target`,"alpine:3.21","sh","-c","umask 077; cat > /run/target/credential"],t)}async removeVolume(e){await Zn(["volume","rm",e],void 0,!0)}async inspect(e){let t=await Zn(["inspect",e],void 0,!0);if(t.code!==0)return;return JSON.parse(t.stdout)[0]}async run(e){await Zn(["run",...e])}async exec(e,t,r){return(await Zn(["exec","-i",e,...t],r)).stdout}async update(e,t){await Zn(["update",...t,e])}async restart(e){await Zn(["restart",e])}async remove(e){await Zn(["rm","--force",e],void 0,!0)}async logs(e,t){let r=await Zn(["logs","--tail",String(Math.min(2000,Math.max(1,t))),e],void 0,!0);return`${r.stdout}${r.stderr}`.slice(-262144)}async stats(e){let t=await Zn(["stats","--no-stream","--format","{{json .}}",e],void 0,!0);if(t.code!==0||!t.stdout.trim())return{};let r=JSON.parse(t.stdout.trim());return{cpuPercent:String(r.CPUPerc??""),memoryUsage:String(r.MemUsage??""),memoryPercent:String(r.MemPerc??""),networkIo:String(r.NetIO??""),blockIo:String(r.BlockIO??""),pids:Number(r.PIDs??0)}}}var fv={postgres:{image:"postgres:17-alpine",port:5432,dataPath:"/var/lib/postgresql/data"},mysql:{image:"mysql:8.4",port:3306,dataPath:"/var/lib/mysql"},mariadb:{image:"mariadb:11.7",port:3306,dataPath:"/var/lib/mysql"},redis:{image:"redis:7.4-alpine",port:6379,dataPath:"/data"},mongodb:{image:"mongo:8.0",port:27017,dataPath:"/data/db"}};function Gi(e,t="app"){let r=String(e??t);if(!/^[A-Za-z_][A-Za-z0-9_]{0,62}$/.test(r))throw Error("Database identifiers must be letters, numbers, or underscores.");return r}function ns(e){if(!/^[a-z0-9][a-z0-9_.-]{1,62}$/i.test(e))throw Error("Runtime placement must be a valid container identifier.");return`tscloud-data-${e.toLowerCase()}`}function hv(e,t){let r=e.desiredState;return e[t]??(r&&typeof r==="object"&&!Array.isArray(r)?r[t]:void 0)}function wa(e){return e.Config?.Labels??{}}class Ze{runtime;backupRoot;constructor(e=new Gg,t=A(process.cwd(),"backups","data")){this.runtime=e;this.backupRoot=t}async observe(e){let t=ns(e),r=await this.runtime.inspect(t);if(!r)throw Error(`Data container ${t} was not found.`);let n=wa(r),i=await this.runtime.stats(t),o=r.NetworkSettings?.Ports??{},s=Object.values(o).flat().find(Boolean);return{providerId:t,status:r.State?.Status??"unknown",healthy:r.State?.Health?.Status??null,engine:n["ts-cloud.engine"]??null,engineVersion:n["ts-cloud.engine-version"]??null,username:n["ts-cloud.username"]??null,database:n["ts-cloud.database"]??null,endpoint:s?.HostIp||"127.0.0.1",port:s?.HostPort?Number(s.HostPort):null,image:r.Config?.Image??null,startedAt:r.State?.StartedAt??null,metrics:i}}async apply(e,t){let r=String(e.id),n=ns(r),i=String(e.engine);if(i==="libsql")throw Error("libSQL requires an explicitly configured runtime image.");let o=fv[i];if(!o)throw Error(`Unsupported runtime data engine ${i}.`);if(!t)throw Error(`${i} requires a managed credential.`);if(e.publicExposure===!0)throw Error("Container public exposure requires an external reviewed firewall policy; direct publishing is refused.");let s=Gi(e.username),c=Gi(hv(e,"database")),l=`${n}-secret`,a=`${n}-data`,m=i==="redis"?`appendonly yes
|
|
46
|
+
protected-mode yes
|
|
47
|
+
requirepass ${t.replaceAll("\\","\\\\").replaceAll(`
|
|
48
|
+
`,"")}
|
|
49
|
+
`:t;await this.runtime.ensureNetwork("ts-cloud-data"),await this.runtime.seedSecret(l,m);let E=["-d","--name",n,"--restart","unless-stopped","--network","ts-cloud-data","--label","managed-by=ts-cloud","--label",`ts-cloud.engine=${i}`,"--label",`ts-cloud.engine-version=${e.engineVersion??""}`,"--label",`ts-cloud.username=${s}`,"--label",`ts-cloud.database=${c}`,"-p",`127.0.0.1:${o.port}:${o.port}`,"-v",`${a}:${o.dataPath}`,"-v",`${l}:/run/ts-cloud-secrets:ro`];if(i==="postgres")E.push("-e",`POSTGRES_USER=${s}`,"-e",`POSTGRES_DB=${c}`,"-e","POSTGRES_PASSWORD_FILE=/run/ts-cloud-secrets/credential");if(i==="mysql"||i==="mariadb")E.push("-e",`MYSQL_USER=${s}`,"-e",`MYSQL_DATABASE=${c}`,"-e","MYSQL_PASSWORD_FILE=/run/ts-cloud-secrets/credential","-e","MYSQL_ROOT_PASSWORD_FILE=/run/ts-cloud-secrets/credential");if(i==="mongodb")E.push("-e",`MONGO_INITDB_ROOT_USERNAME=${s}`,"-e","MONGO_INITDB_ROOT_PASSWORD_FILE=/run/ts-cloud-secrets/credential");if(E.push(o.image),i==="redis")E.push("redis-server","/run/ts-cloud-secrets/credential");return await this.runtime.run(E),{providerId:n,status:"starting",engine:i,endpoint:"127.0.0.1",port:o.port,username:s,database:c}}async exportLogicalBackup(e){let t=ns(e),r=await this.runtime.inspect(t);if(!r)throw Error(`Data container ${t} was not found.`);let n=wa(r),i=n["ts-cloud.engine"],o=Gi(n["ts-cloud.username"]),s=Gi(n["ts-cloud.database"]),c;if(i==="postgres")c=await this.runtime.exec(t,["sh","-c",'export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec pg_dumpall --clean --if-exists -U "$POSTGRES_USER"']);else if(i==="mysql"||i==="mariadb")c=await this.runtime.exec(t,["sh","-c",'export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysqldump -u root --all-databases --single-transaction --add-drop-database --routines --events --triggers']);else throw Error(`${i} does not support engine-native SQL backups.`);return{body:new TextEncoder().encode(c),engine:i,database:s,username:o,engineVersion:n["ts-cloud.engine-version"]||void 0}}async restoreLogicalBackup(e){let t=ns(e.sourceId),r=ns(e.targetId),n=await this.runtime.inspect(t);if(!n)throw Error(`Data container ${t} was not found.`);let i=wa(n),o=i["ts-cloud.engine"],s=Gi(i["ts-cloud.username"]),c=Gi(i["ts-cloud.database"]);if(!["postgres","mysql","mariadb"].includes(o))throw Error(`${o} does not support engine-native SQL restores.`);if(!e.inPlace){if(e.sourceId===e.targetId)throw Error("An isolated restore requires a distinct target identifier.");if(await this.runtime.inspect(r))throw Error(`Restore target ${r} already exists.`);await this.apply({id:e.targetId,engine:o,engineVersion:i["ts-cloud.engine-version"]??"",username:s,database:c,publicExposure:!1},e.credential)}let l=o==="postgres"?["sh","-c",'export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d postgres']:["sh","-c",'export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysql -u root'],a=new TextDecoder("utf-8",{fatal:!0}).decode(e.body),m;for(let E=0;E<30;E++)try{await this.runtime.exec(r,l,a);let k=o==="postgres"?["sh","-c",'export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec psql -U "$POSTGRES_USER" -Atc "SELECT 1"']:["sh","-c",'export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysql -u root -N -e "SELECT 1"'];if((await this.runtime.exec(r,k)).trim()!=="1")throw Error("Restored database health probe returned an unexpected result.");return{status:"available",providerId:r,engine:o,database:c,username:s,healthy:!0}}catch(k){if(m=k,E<29)await Bun.sleep(1000)}throw m instanceof Error?m:Error("Restored database did not become ready.")}async removeRestoredService(e){let t=ns(e);await this.runtime.remove(t),await this.runtime.removeVolume(`${t}-secret`),await this.runtime.removeVolume(`${t}-data`)}async backup(e,t){let r=await this.exportLogicalBackup(e),{engine:n,database:i,username:o}=r,s=String(t.snapshotId??`${e}-${new Date().toISOString().replace(/[^0-9]/g,"").slice(0,14)}`);if(!/^[A-Za-z0-9_.-]{2,120}$/.test(s))throw Error("Backup identifier contains unsupported characters.");await pv(this.backupRoot,{recursive:!0,mode:448});let c=mv(this.backupRoot,`${s}.sql`);return await gv(c,r.body,{mode:384}),{status:"available",backupId:s,path:c,engine:n,database:i,username:o}}async execute(e,t,r,n){let i=ns(e);if(t==="observe")return this.observe(e);if(t==="backup")return this.backup(e,r);if(t==="restart")return await this.runtime.restart(i),{status:"restarting"};if(t==="logs"||t==="slow_queries")return{logs:await this.runtime.logs(i,Number(r.lines)||500)};if(t==="databases"||t==="users"){let o=await this.runtime.inspect(i);if(!o)throw Error(`Data container ${i} was not found.`);let s=wa(o),c=s["ts-cloud.engine"],l=Gi(s["ts-cloud.username"]),a=String(r.operation??"list");if(!["postgres","mysql","mariadb"].includes(c))throw Error(`${t} is available only for SQL runtime engines.`);if(t==="users"&&a!=="list")throw Error("Creating users requires a referenced secondary credential.");if(a==="list"){let m=c==="postgres"?["sh","-c",`export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec psql -U "$POSTGRES_USER" -Atc '${t==="databases"?"SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname":"SELECT usename FROM pg_user ORDER BY usename"}'`]:["sh","-c",`export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysql -u root -N -e '${t==="databases"?"SHOW DATABASES":"SELECT User FROM mysql.user ORDER BY User"}'`],E=await this.runtime.exec(i,m);return{[t]:E.split(`
|
|
50
|
+
`).map((k)=>k.trim()).filter(Boolean)}}if(t==="databases"&&["create","delete"].includes(a)){let m=Gi(r.database);if(a==="delete"&&r.confirm!==m)throw Error(`Type ${m} to confirm logical database deletion.`);let E=c==="postgres"?`${a==="create"?"CREATE":"DROP"} DATABASE "${m}";
|
|
51
|
+
`:`${a==="create"?"CREATE":"DROP"} DATABASE \`${m}\`;
|
|
52
|
+
`,k=c==="postgres"?["sh","-c",'export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec psql -U "$POSTGRES_USER"']:["sh","-c",'export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysql -u root'];return await this.runtime.exec(i,k,E),{status:"available",database:m,operation:a}}throw Error(`Unsupported ${t} operation ${a}.`)}if(t==="resize"){let o=[];if(r.memoryMb)o.push("--memory",`${Number(r.memoryMb)}m`);if(r.cpus)o.push("--cpus",String(Number(r.cpus)));if(!o.length)throw Error("Resize requires memoryMb or cpus.");return await this.runtime.update(i,o),{status:"running",memoryMb:r.memoryMb??null,cpus:r.cpus??null}}if(t==="rotate"){if(!n)throw Error("Credential rotation requires a generated secret.");let o=await this.runtime.inspect(i);if(!o)throw Error(`Data container ${i} was not found.`);let s=wa(o),c=s["ts-cloud.engine"],l=Gi(s["ts-cloud.username"]),a=n.replaceAll("'","''").replaceAll(`
|
|
53
|
+
`,"");if(c==="postgres")await this.runtime.exec(i,["sh","-c",'export PGPASSWORD="$(cat /run/ts-cloud-secrets/credential)"; exec psql -U "$POSTGRES_USER"'],`ALTER USER "${l}" PASSWORD '${a}';
|
|
54
|
+
`);else if(c==="mysql"||c==="mariadb")await this.runtime.exec(i,["sh","-c",'export MYSQL_PWD="$(cat /run/ts-cloud-secrets/credential)"; exec mysql -u root'],`ALTER USER '${l}'@'%' IDENTIFIED BY '${a}';
|
|
55
|
+
`);else if(c!=="redis")throw Error(`${c} credential rotation requires an engine runner.`);let m=c==="redis"?`appendonly yes
|
|
56
|
+
protected-mode yes
|
|
57
|
+
requirepass ${n.replaceAll("\\","\\\\").replaceAll(`
|
|
58
|
+
`,"")}
|
|
59
|
+
`:n;if(await this.runtime.seedSecret(`${i}-secret`,m),c==="redis")await this.runtime.restart(i);return{status:c==="redis"?"restarting":"running",username:l}}if(t==="delete"){if(r.retention==="retain")return{status:"retained"};let o=await this.backup(e,r);return await this.runtime.remove(i),await this.runtime.removeVolume(`${i}-secret`),await this.runtime.removeVolume(`${i}-data`),{status:"deleted",finalBackupId:o.backupId??null,backupPath:o.path??null}}if(t==="expose")throw Error("Direct container exposure is refused; use a reviewed firewall and proxy policy.");throw Error(`${t} requires a configured engine lifecycle runner.`)}}import{createCipheriv as yv,createDecipheriv as bv,createHash as Kg,randomBytes as Sv}from"node:crypto";class Wt{controlPlane;now;key;constructor(e,t,r=()=>new Date){this.controlPlane=e;this.now=r;if(!t)throw Error("Data-service encryption key is required.");this.key=Kg("sha256").update(`ts-cloud:data-services:${t}`).digest()}encrypt(e){let t=Sv(12),r=yv("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("Encrypted data-service secret is unavailable.");try{let o=bv("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")}catch{throw Error("Encrypted data-service secret could not be decrypted.")}}async put(e,t){if(!/^secret:\/\/data-services\/[A-Za-z0-9._/-]+$/.test(e))throw Error("Invalid data-service secret reference.");if(!t)throw Error("Data-service secret cannot be empty.");let r=this.now().toISOString();this.controlPlane.database.run("INSERT INTO data_service_secrets (reference,ciphertext,fingerprint,created_at,updated_at) VALUES (?,?,?,?,?) ON CONFLICT(reference) DO UPDATE SET ciphertext=excluded.ciphertext,fingerprint=excluded.fingerprint,updated_at=excluded.updated_at",[e,this.encrypt(t),Kg("sha256").update(t).digest("hex"),r,r])}async resolve(e){let t=this.controlPlane.database.query("SELECT ciphertext FROM data_service_secrets WHERE reference = ?").get(e);if(!t)throw Error("Data-service secret was not found.");return this.decrypt(t.ciphertext)}async remove(e){this.controlPlane.database.run("DELETE FROM data_service_secrets WHERE reference = ?",[e])}}import{existsSync as Ia}from"node:fs";import{mkdir as fc,readdir as vv,rename as fu,rm as $s}from"node:fs/promises";import{relative as wv,resolve as sn,sep as hc}from"node:path";function is(e,t){if(t==="gzip")return Buffer.from(Bun.gzipSync(Uint8Array.from(e)));if(t==="zstd")return Buffer.from(Bun.zstdCompressSync(Uint8Array.from(e)));return Buffer.from(e)}function Ki(e,t){if(t==="gzip")return Buffer.from(Bun.gunzipSync(Uint8Array.from(e)));if(t==="zstd")return Buffer.from(Bun.zstdDecompressSync(Uint8Array.from(e)));return Buffer.from(e)}async function hu(e,t){let r=Bun.spawn(["tar",...e],{stdin:t?Buffer.from(t):void 0,stdout:"pipe",stderr:"pipe"}),[n,i,o]=await Promise.all([r.exited,new Response(r.stdout).arrayBuffer(),new Response(r.stderr).text()]);if(n!==0)throw Error(o.trim()||`tar exited with status ${n}.`);return{stdout:Buffer.from(i),stderr:o}}function Iv(e){let t=e.replaceAll("\\","/").replace(/^\.\//,"");return!!t&&!t.startsWith("/")&&!t.split("/").includes("..")}class Yg{async create(e,t,r){return(await hu(["-C",e,"-cf","-",...r.map((i)=>`--exclude=${i}`),"--",...t])).stdout}async extract(e,t){await fc(t,{recursive:!0,mode:448}),await hu(["-C",t,"-xf","-"],e)}async inspect(e){let t=await hu(["-tf","-"],e),r=t.stdout.toString().split(`
|
|
60
|
+
`).filter(Boolean);if(r.some((n)=>!Iv(n)))throw Error("Backup archive contains an unsafe path.");return{entries:r,bytes:e.byteLength}}}function Qg(e,t){if(!t.trim())throw Error("File backup paths cannot be empty.");let r=sn(e,t),n=wv(e,r);if(n===".."||n.startsWith(`..${hc}`)||n==="")throw Error(`File backup path ${t} is outside the project root.`);return n}function mc(e){let t=String(e.targetId??e.path??"");if(!/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/.test(t))throw Error("File restores require a safe target name.");return t}class yu{runtime;root;restoreRoot;constructor(e,t=new Yg,r=A(e,"restores","files")){this.runtime=t;this.root=sn(e),this.restoreRoot=sn(r)}paths(e){let t=[...new Set(e.includePatterns.map((r)=>Qg(this.root,r)))];if(!t.length)throw Error("File backup policies require at least one project-relative path.");for(let r of t)if(!Ia(sn(this.root,r)))throw Error(`File backup path ${r} was not found.`);return t.filter((r)=>!t.some((n)=>n!==r&&r.startsWith(`${n}${hc}`)))}async create(e,t){let r=this.paths(e),n=await this.runtime.create(this.root,r,e.excludePatterns),i=await this.runtime.inspect(n),o=e.compression??"none",s=is(n,o),c=String(t.operation?.id??new Date().toISOString()).replace(/[^A-Za-z0-9]/g,"").slice(0,32);return{mode:"object",key:`${e.projectId}/files/${c}.tar${o==="none"?"":o==="gzip"?".gz":".zst"}`,body:s,contentType:o==="gzip"?"application/gzip":o==="zstd"?"application/zstd":"application/x-tar",manifest:{archive:"tar",compression:o,sourcePaths:r,excluded:e.excludePatterns,entries:i.entries.length},toolVersion:"system-tar"}}async restore(e,t,r,n){if(!t)throw Error("File restore requires an archive payload.");let i=Ki(t,String(e.manifest.compression??"none"));if(await this.runtime.inspect(i),r.restoreMode==="in_place"){let s=sn(this.restoreRoot,`.staging-${mc(r)}`),c=sn(this.restoreRoot,`.rollback-${mc(r)}`),l=Array.isArray(e.manifest.sourcePaths)?e.manifest.sourcePaths.map(String):[];if(!l.length)throw Error("File recovery point has no source path manifest.");await $s(s,{recursive:!0,force:!0}),await $s(c,{recursive:!0,force:!0}),await this.runtime.extract(i,s),await fc(c,{recursive:!0,mode:448});let a=[];try{for(let m of l){let E=sn(this.root,Qg(this.root,m)),k=sn(s,m),O=sn(c,m);if(await fc(sn(O,".."),{recursive:!0}),Ia(E))await fu(E,O);await fc(sn(E,".."),{recursive:!0}),await fu(k,E),a.push(m)}}catch(m){for(let E of a.reverse()){let k=sn(this.root,E),O=sn(c,E);if(await $s(k,{recursive:!0,force:!0}),Ia(O))await fu(O,k)}throw m}finally{await $s(s,{recursive:!0,force:!0})}return await $s(c,{recursive:!0,force:!0}),{path:this.root,restoredPaths:l,inPlace:!0}}let o=sn(this.restoreRoot,mc(r));if(Ia(o))throw Error("The isolated file restore target already exists.");return await this.runtime.extract(i,o),{path:o,isolated:!0}}async verify(e,t,r){let n=Ki(t,String(e.manifest.compression??"none")),i=await this.runtime.inspect(n);return{archive:"tar",entries:i.entries.length,uncompressedBytes:i.bytes}}async validateHealth(e,t){let r=String(e.path??"");if(!r||!r.startsWith(`${this.restoreRoot}${hc}`)||!Ia(r))throw Error("Isolated file restore target was not found.");let n=await vv(r);return{healthy:!0,path:r,topLevelEntries:n.length}}async cleanup(e,t){let r=mc(e),n=sn(this.restoreRoot,r);if(!n.startsWith(`${this.restoreRoot}${hc}`))throw Error("Refusing to clean a file restore outside the restore root.");await $s(n,{recursive:!0,force:!0})}}class bu{services;secrets;transport;constructor(e,t,r=new Ze){this.services=e;this.secrets=t;this.transport=r}async create(e,t){if(!e.dataServiceId)throw Error("Logical database backups require a data service.");let r=this.services.get(e.dataServiceId);if(!r)throw Error("Logical database service was not found.");if(!["container","server"].includes(r.provider))throw Error("Logical database backups require an on-box data service.");let n=await this.transport.exportLogicalBackup(r.id),i=e.compression??"none",o=is(n.body,i),s=String(t.operation?.id??new Date().toISOString()).replace(/[^A-Za-z0-9]/g,"").slice(0,32);return{mode:"object",key:`${e.projectId}/databases/${r.id}/${s}.sql${i==="none"?"":i==="gzip"?".gz":".zst"}`,body:o,contentType:i==="gzip"?"application/gzip":i==="zstd"?"application/zstd":"application/sql",engineVersion:n.engineVersion,toolVersion:"engine-native",manifest:{format:"logical-sql-v1",sourceDataServiceId:r.id,engine:n.engine,database:n.database,username:n.username,compression:i}}}async restore(e,t,r,n){if(!t)throw Error("Logical database backup body is unavailable.");let i=String(e.dataServiceId??e.manifest.sourceDataServiceId??""),o=String(r.dataServiceId??r.targetId??""),s=r.inPlace===!0;if(!i||!o)throw Error("Logical database restore requires source and target identifiers.");if(s&&o!==i)throw Error("An in-place restore must target the source data service.");let c=this.services.get(i);if(!c?.credentialRef)throw Error("Logical database credential reference was not found.");let l=await this.secrets.resolve(c.credentialRef);return this.transport.restoreLogicalBackup({sourceId:i,targetId:o,body:Ki(t,String(e.manifest.compression??"none")),credential:l,inPlace:s})}async cleanup(e,t){if(e.inPlace===!0)throw Error("In-place database restores cannot be cleaned as drills.");let r=String(e.dataServiceId??e.targetId??"");if(!r)throw Error("Database cleanup requires a target identifier.");await this.transport.removeRestoredService(r)}}var Su=/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/;async function os(e,t,r=!1){let n=Bun.spawn(["docker",...e],{stdin:t?"pipe":"ignore",stdout:"pipe",stderr:"pipe"}),i=new Response(n.stdout).arrayBuffer(),o=new Response(n.stderr).text();if(t)n.stdin.write(t),n.stdin.end();let[s,c,l]=await Promise.all([n.exited,i,o]);if(s!==0&&!r)throw Error(`Docker volume command failed (${s}): ${l.trim()}`);return{code:s,stdout:Buffer.from(c),stderr:l}}class Xg{async exists(e){return(await os(["volume","inspect",e],void 0,!0)).code===0}async export(e){return(await os(["run","--rm","-v",`${e}:/source:ro`,"alpine:3.21","tar","-C","/source","-czf","-","."])).stdout}async import(e,t,r=!1){if(!await this.exists(e))await os(["volume","create",e]);try{if(r)await os(["run","--rm","-v",`${e}:/target`,"alpine:3.21","sh","-c","find /target -mindepth 1 -delete"]);await os(["run","--rm","-i","-v",`${e}:/target`,"alpine:3.21","tar","-C","/target","--no-same-owner","-xzf","-"],t)}catch(n){throw await this.remove(e),n}}async remove(e){await os(["volume","rm",e],void 0,!0)}async probe(e){let t=(await os(["run","--rm","-v",`${e}:/target:ro`,"alpine:3.21","sh","-c",`find /target -mindepth 1 -printf '%s\\n' | awk '{n+=1;b+=$1} END {print n ":" b}'`])).stdout.toString(),[r,n]=t.trim().split(":").map(Number);if(!Number.isFinite(r)||!Number.isFinite(n))throw Error("Restored volume health probe returned invalid output.");return{entries:r,bytes:n}}}class vu{runtime;constructor(e=new Xg){this.runtime=e}async create(e,t){let r=String(e.includePatterns?.[0]??e.resourceId??"");if(!Su.test(r))throw Error("Volume backups require a valid named-volume resource identifier.");if(!await this.runtime.exists(r))throw Error(`Volume ${r} was not found.`);let n=await this.runtime.export(r),i=Buffer.from(Bun.gunzipSync(Uint8Array.from(n))),o=e.compression??"gzip",s=o==="gzip"?n:is(i,o),c=String(t.operation?.id??new Date().toISOString()).replace(/[^A-Za-z0-9]/g,"").slice(0,32);return{mode:"object",key:`${e.projectId}/volumes/${r}/${c}.tar${o==="none"?"":o==="gzip"?".gz":".zst"}`,body:s,contentType:o==="gzip"?"application/gzip":o==="zstd"?"application/zstd":"application/x-tar",toolVersion:"alpine-tar",manifest:{format:"docker-volume-tar-v1",archive:"tar",compression:o,sourceVolume:r}}}async restore(e,t,r,n){if(!t)throw Error("Volume backup body is unavailable.");let i=String(e.manifest.sourceVolume??e.resourceId??""),o=String(r.volumeName??r.targetId??"");if(!Su.test(o))throw Error("Volume restore requires a valid target volume name.");if(o===i&&r.inPlace!==!0)throw Error("An isolated volume restore requires a distinct target.");let s=await this.runtime.exists(o);if(!r.inPlace&&s)throw Error(`Restore target volume ${o} already exists.`);if(r.inPlace===!0&&o!==i)throw Error("An in-place volume restore must target the source volume.");if(r.inPlace===!0&&!s)throw Error("The in-place target volume was not found.");let c=String(e.manifest.compression??"gzip"),l=c==="gzip"?Buffer.from(t):Buffer.from(Bun.gzipSync(Uint8Array.from(Ki(t,c))));await this.runtime.import(o,l,r.inPlace===!0);let a=await this.runtime.probe(o);return{volumeName:o,healthy:!0,...a}}async cleanup(e,t){if(e.inPlace===!0)throw Error("In-place volume restores cannot be cleaned as drills.");let r=String(e.volumeName??e.targetId??"");if(!Su.test(r))throw Error("Volume cleanup requires a valid target volume name.");await this.runtime.remove(r)}}import{existsSync as wu}from"node:fs";import{mkdir as Cv,readFile as Zg,rm as Ev,writeFile as em}from"node:fs/promises";import{basename as om,resolve as ko,sep as tm}from"node:path";import{Database as Tv}from"bun:sqlite";function rm(e){let t=String(e.targetId??e.path??"");if(!/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/.test(t))throw Error("Control-plane restores require a safe target name.");return t}function nm(e){let t=JSON.parse(Buffer.from(e).toString());if(t.format!=="ts-cloud-control-plane-v1"||!t.database)throw Error("Control-plane backup archive is invalid.");if(!Array.isArray(t.config)||t.config.some((r)=>om(r.name)!==r.name))throw Error("Control-plane backup contains an unsafe config path.");return t}function im(e){let t=Tv.deserialize(Uint8Array.from(e));try{let r=t.query("PRAGMA integrity_check").get()?.integrity_check??"unknown",n=t.query("SELECT count(*) AS count FROM sqlite_master WHERE type='table'").get()?.count??0;if(r!=="ok")throw Error(`Restored control-plane integrity check failed: ${r}.`);return{integrity:r,tables:n}}finally{t.close()}}class Iu{controlPlane;root;restoreRoot;constructor(e,t,r=A(t,"restores","control-plane")){this.controlPlane=e;this.root=ko(t),this.restoreRoot=ko(r)}async create(e,t){let r=e.includePatterns.length?e.includePatterns:["cloud.config.ts"],n=[];for(let l of r){let a=om(l),m=ko(this.root,a);if(a!==l&&l!==`./${a}`)throw Error("Control-plane config paths must be project-root files.");if(wu(m))n.push({name:a,body:(await Zg(m)).toString("base64")})}let i={format:"ts-cloud-control-plane-v1",createdAt:new Date().toISOString(),database:Buffer.from(this.controlPlane.database.serialize()).toString("base64"),config:n},o=e.compression??"none",s=is(Buffer.from(JSON.stringify(i)),o),c=String(t.operation?.id??i.createdAt).replace(/[^A-Za-z0-9]/g,"").slice(0,32);return{mode:"object",key:`${e.projectId}/control-plane/${c}.json${o==="none"?"":o==="gzip"?".gz":".zst"}`,body:s,contentType:o==="gzip"?"application/gzip":o==="zstd"?"application/zstd":"application/vnd.ts-cloud.control-plane+json",manifest:{format:i.format,configFiles:n.map((l)=>l.name),sensitive:!0,compression:o},toolVersion:"bun-sqlite-serialize"}}async restore(e,t,r,n){if(!t)throw Error("Control-plane restore requires an archive payload.");if(r.restoreMode==="in_place")throw Error("A live control plane can only be restored into an isolated recovery target.");let i=nm(Ki(t,String(e.manifest.compression??"none"))),o=ko(this.restoreRoot,rm(r));if(wu(o))throw Error("The isolated control-plane restore target already exists.");await Cv(o,{recursive:!0,mode:448}),await em(ko(o,"control-plane.sqlite"),Buffer.from(i.database,"base64"),{mode:384});for(let s of i.config)await em(ko(o,s.name),Buffer.from(s.body,"base64"),{mode:384});return{path:o,isolated:!0,configFiles:i.config.length}}async verify(e,t,r){let n=nm(Ki(t,String(e.manifest.compression??"none")));return{...im(Buffer.from(n.database,"base64")),configFiles:n.config.length}}async validateHealth(e,t){let r=String(e.path??""),n=ko(r,"control-plane.sqlite");if(!r.startsWith(`${this.restoreRoot}${tm}`)||!wu(n))throw Error("Isolated control-plane database was not found.");return{healthy:!0,...im(await Zg(n))}}async cleanup(e,t){let r=ko(this.restoreRoot,rm(e));if(!r.startsWith(`${this.restoreRoot}${tm}`))throw Error("Refusing to clean a control-plane restore outside the restore root.");await Ev(r,{recursive:!0,force:!0})}}import{createHash as Av}from"node:crypto";function Cu(e,t){return e.find((r)=>r.startsWith(`${t}:`))?.slice(t.length+1)}function kv(e){let t=Cu(e.includePatterns,"resource")??e.includePatterns.find((i)=>i.startsWith("arn:")),r=Cu(e.includePatterns,"role"),n=Cu(e.includePatterns,"vault")??"Default";if(!t?.startsWith("arn:"))throw Error("Infrastructure backups require resource:<arn> in include patterns.");if(!r?.startsWith("arn:"))throw Error("Infrastructure backups require role:<iam-role-arn> in include patterns.");if(!/^[A-Za-z0-9_.-]{2,50}$/.test(n))throw Error("Infrastructure backup vault name is invalid.");return{resourceArn:t,roleArn:r,vaultName:n}}async function Rv(e,t,r){for(;;){r.throwIfCancellationRequested(),r.heartbeat();let n=await e.describeBackupJob(t),i=String(n.State??"");if(r.checkpoint("provider_backup",`AWS Backup job ${t} is ${i||"pending"}.`),i==="COMPLETED"&&n.RecoveryPointArn)return{recoveryPointArn:n.RecoveryPointArn,sizeBytes:Number(n.BackupSizeInBytes??0)};if(["ABORTED","EXPIRED","FAILED"].includes(i))throw Error(`AWS Backup job ${t} failed: ${n.StatusMessage??i}.`);await Bun.sleep(5000)}}async function Pv(e,t,r){for(;;){r.throwIfCancellationRequested(),r.heartbeat();let n=await e.describeRestoreJob(t),i=String(n.Status??"");if(r.checkpoint("provider_restore",`AWS Backup restore ${t} is ${i||"pending"}.`),i==="COMPLETED"&&n.CreatedResourceArn)return n.CreatedResourceArn;if(["ABORTED","FAILED"].includes(i))throw Error(`AWS Backup restore ${t} failed: ${n.StatusMessage??i}.`);await Bun.sleep(5000)}}class Eu{client;constructor(e=new va){this.client=e}async create(e,t){let r=kv(e),n=String(t.operation.id).replace(/[^A-Za-z0-9-]/g,"").slice(0,64),i=await this.client.startBackupJob({BackupVaultName:r.vaultName,ResourceArn:r.resourceArn,IamRoleArn:r.roleArn,IdempotencyToken:n}),o=await Rv(this.client,i.BackupJobId,t),s=`sha256:${Av("sha256").update(o.recoveryPointArn).digest("hex")}`;return{mode:"external",uri:o.recoveryPointArn,checksum:s,sizeBytes:o.sizeBytes,toolVersion:"aws-backup-api",manifest:{provider:"aws_backup",resourceArn:r.resourceArn,roleArn:r.roleArn,vaultName:r.vaultName,providerBackupJobId:i.BackupJobId,recoveryPointArn:o.recoveryPointArn}}}async verifyExternal(e,t){let r=String(e.manifest.providerBackupJobId??""),n=await this.client.describeBackupJob(r);if(n.State!=="COMPLETED"||n.RecoveryPointArn!==e.uri)throw Error(`AWS Backup recovery point verification failed: ${n.StatusMessage??n.State??"unknown"}.`);return{state:n.State,recoveryPointArn:n.RecoveryPointArn,sizeBytes:Number(n.BackupSizeInBytes??e.sizeBytes)}}async restore(e,t,r,n){if(r.inPlace===!0)throw Error("AWS Backup infrastructure restores must create isolated resources.");let i=String(r.roleArn??e.manifest.roleArn??""),o=r.metadata&&typeof r.metadata==="object"&&!Array.isArray(r.metadata)?Object.fromEntries(Object.entries(r.metadata).map(([l,a])=>[l,String(a)])):{};if(!i.startsWith("arn:"))throw Error("AWS Backup restore requires an IAM role ARN.");if(!Object.keys(o).length)throw Error("AWS Backup restore requires provider restore metadata.");let s=await this.client.startRestoreJob({RecoveryPointArn:e.uri,IamRoleArn:i,Metadata:o,IdempotencyToken:String(n.operation.id).replace(/[^A-Za-z0-9-]/g,"").slice(0,64)}),c=await Pv(this.client,s.RestoreJobId,n);return{providerRestoreJobId:s.RestoreJobId,createdResourceArn:c,isolated:!0,healthy:!0}}async validateHealth(e,t){let r=String(e.createdResourceArn??"");return{healthy:r.startsWith("arn:"),createdResourceArn:r}}async deleteExternal(e,t){await this.client.deleteRecoveryPoint(String(e.manifest.vaultName??""),e.uri)}}import{existsSync as UI}from"node:fs";import{join as _f}from"node:path";import{pathToFileURL as zI}from"node:url";import{existsSync as sm,statSync as am}from"fs";import{resolve as Ea}from"path";import xv from"process";import{existsSync as _v,mkdirSync as yx,readdirSync as bx,readFileSync as Nv,writeFileSync as Sx}from"fs";import{homedir as Ms}from"os";import{dirname as Ix,resolve as Mi}from"path";import Kc from"process";import{existsSync as cm,statSync as dm}from"fs";import{existsSync as qu,mkdirSync as $v,readdirSync as Mv,writeFileSync as Lv}from"fs";import{homedir as Ls}from"os";import{dirname as um,resolve as Bn}from"path";import as from"process";import{join as Bv,relative as jv,resolve as lm}from"path";import Mc from"process";import{existsSync as Ym,mkdirSync as Ox,readdirSync as _x,writeFileSync as Nx}from"fs";import{homedir as Tu}from"os";import{dirname as Lx,resolve as an}from"path";import Aa from"process";import{join as Fv,relative as Uv,resolve as pm}from"path";import Lc from"process";import{existsSync as Xm,mkdirSync as zx,readdirSync as Vx,writeFileSync as qx}from"fs";import{dirname as Wx,resolve as Bc}from"path";import Ju from"process";import{Buffer as Ro}from"buffer";import{createCipheriv as zv,createDecipheriv as Vv,randomBytes as Au}from"crypto";import{closeSync as ku,createReadStream as gm,createWriteStream as qv,existsSync as Ru,fsyncSync as mm,openSync as fm,writeFileSync as Jv}from"fs";import{access as Wv,constants as hm,mkdir as Hv,readdir as yc,rename as ym,stat as Bs,unlink as bc,writeFile as Pu}from"fs/promises";import{join as js}from"path";import Fr from"process";import{pipeline as Gv}from"stream/promises";import{createGzip as bm}from"zlib";import Fs from"process";import Xi from"process";import{Buffer as Qi}from"buffer";import{createCipheriv as Kv,createDecipheriv as Qv,randomBytes as xu}from"crypto";import{closeSync as Du,createReadStream as Sm,createWriteStream as Yv,existsSync as Sc,fsyncSync as vm,openSync as wm,writeFileSync as Xv}from"fs";import{access as Zv,constants as Im,mkdir as ew,readdir as vc,rename as Cm,stat as Us,unlink as wc,writeFile as Ou}from"fs/promises";import{isAbsolute as tw,join as zs,resolve as rw}from"path";import bt from"process";import{pipeline as nw}from"stream/promises";import{createGzip as Em}from"zlib";import Vs from"process";import Zi from"process";import Ic from"process";import{existsSync as Cc}from"fs";import{resolve as _u}from"path";import{existsSync as iw}from"fs";import{existsSync as ow,readdirSync as sw}from"fs";import{extname as Nu,resolve as Tm}from"path";import aw from"process";import{join as cw,relative as dw,resolve as Am}from"path";import jc from"process";import{Buffer as Yi}from"buffer";import{createCipheriv as uw,createDecipheriv as lw,randomBytes as $u}from"crypto";import{closeSync as Mu,createReadStream as km,createWriteStream as pw,existsSync as Ec,fsyncSync as Rm,openSync as Pm,writeFileSync as gw}from"fs";import{access as mw,constants as xm,mkdir as fw,readdir as Tc,rename as Dm,stat as qs,unlink as Ac,writeFile as Lu}from"fs/promises";import{isAbsolute as hw,join as Js,resolve as yw}from"path";import vt from"process";import{pipeline as bw}from"stream/promises";import{createGzip as Om}from"zlib";import Ws from"process";import eo from"process";import Rc from"process";import{existsSync as Pc}from"fs";import{resolve as Wm}from"path";import{existsSync as BI}from"fs";class Hm{cache=new Map;totalHits=0;totalMisses=0;options;constructor(e={}){this.options={enabled:!0,ttl:300000,maxSize:100,keyPrefix:"bunfig:",...e}}generateKey(e,t){let r=t?`:${t}`:"";return`${this.options.keyPrefix}${e}${r}`}isExpired(e){return Date.now()-e.timestamp.getTime()>e.ttl}estimateSize(e){try{return JSON.stringify(e).length}catch{return 1000}}evictIfNeeded(){if(this.cache.size<=this.options.maxSize)return;let e=Array.from(this.cache.entries()).sort(([,r],[,n])=>r.timestamp.getTime()-n.timestamp.getTime()),t=e.length-this.options.maxSize+1;for(let r=0;r<t;r++)this.cache.delete(e[r][0])}set(e,t,r,n){if(!this.options.enabled)return;let i=this.generateKey(e,r),o=n??this.options.ttl,s=this.estimateSize(t);this.cache.set(i,{value:t,timestamp:new Date,ttl:o,hits:0,size:s}),this.evictIfNeeded()}get(e,t){if(!this.options.enabled){this.totalMisses++;return}let r=this.generateKey(e,t),n=this.cache.get(r);if(!n){this.totalMisses++;return}if(this.isExpired(n)){this.cache.delete(r),this.totalMisses++;return}return n.hits++,this.totalHits++,n.value}isFileModified(e,t){try{if(!sm(e))return!0;return am(e).mtime>t}catch{return!0}}getWithFileCheck(e,t){let r=this.get(e,t);if(!r)return;if(this.isFileModified(t,r.fileTimestamp)){this.delete(e,t);return}return r.value}setWithFileCheck(e,t,r,n){try{let i=sm(r)?am(r):null,o=i?i.mtime:new Date;this.set(e,{value:t,fileTimestamp:o},r,n)}catch{this.set(e,t,r,n)}}delete(e,t){let r=this.generateKey(e,t);return this.cache.delete(r)}clear(){this.cache.clear(),this.totalHits=0,this.totalMisses=0}cleanup(){let e=0;for(let[t,r]of this.cache.entries())if(this.isExpired(r))this.cache.delete(t),e++;return e}getStats(){let e=Array.from(this.cache.values()),t=e.reduce((n,i)=>n+i.size,0),r=e.map((n)=>n.timestamp).sort();return{size:t,maxSize:this.options.maxSize,hitRate:this.totalHits+this.totalMisses>0?this.totalHits/(this.totalHits+this.totalMisses):0,totalHits:this.totalHits,totalMisses:this.totalMisses,entries:this.cache.size,oldestEntry:r[0],newestEntry:r[r.length-1]}}export(){let e={};for(let[t,r]of this.cache.entries())e[t]={value:r.value,timestamp:r.timestamp.toISOString(),ttl:r.ttl,hits:r.hits,size:r.size};return e}import(e){this.cache.clear();for(let[t,r]of Object.entries(e))if(typeof r==="object"&&r!==null){let n=r;this.cache.set(t,{value:n.value,timestamp:new Date(n.timestamp),ttl:n.ttl,hits:n.hits,size:n.size})}}}class Gm{metrics=[];maxMetrics=1000;async track(e,t,r={}){let n=performance.now(),i=new Date;try{let o=await t(),s=performance.now()-n;return this.recordMetric({operation:e,duration:s,timestamp:i,...r}),o}catch(o){let s=performance.now()-n;throw this.recordMetric({operation:`${e}:error`,duration:s,timestamp:i,...r}),o}}recordMetric(e){if(this.metrics.push(e),this.metrics.length>this.maxMetrics)this.metrics=this.metrics.slice(-this.maxMetrics)}getStats(e){let t=e?this.metrics.filter((i)=>i.operation===e):this.metrics;if(t.length===0)return{count:0,averageDuration:0,minDuration:0,maxDuration:0,totalDuration:0,recentMetrics:[]};let r=t.map((i)=>i.duration),n=r.reduce((i,o)=>i+o,0);return{count:t.length,averageDuration:n/t.length,minDuration:Math.min(...r),maxDuration:Math.max(...r),totalDuration:n,recentMetrics:t.slice(-10)}}getAllMetrics(){return[...this.metrics]}clearMetrics(){this.metrics=[]}getSlowOperations(e){return this.metrics.filter((t)=>t.duration>e)}}var $c=new Hm,rl=new Gm;var Km=[".ts",".js",".mjs",".cjs",".json",".mts",".cts"];function Qm(e={}){let{name:t="",alias:r}=e,n=["config",".config"];if(t)n.push(t,`.${t}.config`,`${t}.config`,`.${t}`);let i=r===void 0?[]:Array.isArray(r)?r:[r];for(let o of i){if(!o)continue;if(n.push(o,`.${o}.config`,`${o}.config`,`.${o}`),t)n.push(`${t}.${o}.config`,`.${t}.${o}.config`)}return Array.from(new Set(n.filter(Boolean)))}function Dv(e){return Qm(e).flatMap((r)=>Km.map((n)=>Ea(e.directory,`${r}${n}`)))}function Ov(e={}){let t=Ea(e.cwd||xv.cwd());return Array.from(new Set([t,Ea(t,"config"),Ea(t,".config"),e.configDir?Ea(t,e.configDir):void 0].filter((r)=>Boolean(r))))}var Sw=Object.defineProperty,vw=(e)=>e;function ww(e,t){this[e]=vw.bind(null,t)}var Iw=(e,t)=>{for(var r in t)Sw(e,r,{get:t[r],enumerable:!0,configurable:!0,set:ww.bind(t,r)})},Cw=(e,t)=>()=>(e&&(t=e(e=0)),t),Zm={};Iw(Zm,{withErrorRecovery:()=>rf,tryLoadConfig:()=>Ww,loadConfigWithResult:()=>qw,loadConfig:()=>cf,isRetryableError:()=>Bw,isConfigNotFoundError:()=>Lw,isBunfigError:()=>nf,globalPerformanceMonitor:()=>Pa,globalCache:()=>Hs,getEnvOrDefault:()=>jw,generateConfigTypes:()=>Hw,defaultGeneratedDir:()=>hf,defaultConfigDir:()=>ff,deepMergeWithArrayStrategy:()=>al,deepMerge:()=>of,createLibraryConfig:()=>Gw,config:()=>Jw,bunfigPlugin:()=>Kw,applyEnvVarsToConfig:()=>Ta,TypeGenerationError:()=>Xu,SchemaValidationError:()=>Ra,PluginError:()=>el,PerformanceMonitor:()=>il,FileSystemError:()=>Yu,ErrorFactory:()=>Po,EnvVarError:()=>Jc,EnvProcessor:()=>Qc,ConfigValidator:()=>cl,ConfigValidationError:()=>Ku,ConfigNotFoundError:()=>qc,ConfigMergeError:()=>Qu,ConfigLoader:()=>dl,ConfigLoadError:()=>ka,ConfigFileLoader:()=>Yc,ConfigCache:()=>nl,CacheUtils:()=>uf,BunfigError:()=>ri,BrowserConfigError:()=>Zu,ArrayMergeStrategies:()=>gf});class nl{cache=new Map;totalHits=0;totalMisses=0;options;constructor(e={}){this.options={enabled:!0,ttl:300000,maxSize:100,keyPrefix:"bunfig:",...e}}generateKey(e,t){let r=t?`:${t}`:"";return`${this.options.keyPrefix}${e}${r}`}isExpired(e){return Date.now()-e.timestamp.getTime()>e.ttl}estimateSize(e){try{return JSON.stringify(e).length}catch{return 1000}}evictIfNeeded(){if(this.cache.size<=this.options.maxSize)return;let e=Array.from(this.cache.entries()).sort(([,r],[,n])=>r.timestamp.getTime()-n.timestamp.getTime()),t=e.length-this.options.maxSize+1;for(let r=0;r<t;r++)this.cache.delete(e[r][0])}set(e,t,r,n){if(!this.options.enabled)return;let i=this.generateKey(e,r),o=n??this.options.ttl,s=this.estimateSize(t);this.cache.set(i,{value:t,timestamp:new Date,ttl:o,hits:0,size:s}),this.evictIfNeeded()}get(e,t){if(!this.options.enabled){this.totalMisses++;return}let r=this.generateKey(e,t),n=this.cache.get(r);if(!n){this.totalMisses++;return}if(this.isExpired(n)){this.cache.delete(r),this.totalMisses++;return}return n.hits++,this.totalHits++,n.value}isFileModified(e,t){try{if(!cm(e))return!0;return dm(e).mtime>t}catch{return!0}}getWithFileCheck(e,t){let r=this.get(e,t);if(!r)return;if(this.isFileModified(t,r.fileTimestamp)){this.delete(e,t);return}return r.value}setWithFileCheck(e,t,r,n){try{let i=cm(r)?dm(r):null,o=i?i.mtime:new Date;this.set(e,{value:t,fileTimestamp:o},r,n)}catch{this.set(e,t,r,n)}}delete(e,t){let r=this.generateKey(e,t);return this.cache.delete(r)}clear(){this.cache.clear(),this.totalHits=0,this.totalMisses=0}cleanup(){let e=0;for(let[t,r]of this.cache.entries())if(this.isExpired(r))this.cache.delete(t),e++;return e}getStats(){let e=Array.from(this.cache.values()),t=e.reduce((n,i)=>n+i.size,0),r=e.map((n)=>n.timestamp).sort();return{size:t,maxSize:this.options.maxSize,hitRate:this.totalHits+this.totalMisses>0?this.totalHits/(this.totalHits+this.totalMisses):0,totalHits:this.totalHits,totalMisses:this.totalMisses,entries:this.cache.size,oldestEntry:r[0],newestEntry:r[r.length-1]}}export(){let e={};for(let[t,r]of this.cache.entries())e[t]={value:r.value,timestamp:r.timestamp.toISOString(),ttl:r.ttl,hits:r.hits,size:r.size};return e}import(e){this.cache.clear();for(let[t,r]of Object.entries(e))if(typeof r==="object"&&r!==null){let n=r;this.cache.set(t,{value:n.value,timestamp:new Date(n.timestamp),ttl:n.ttl,hits:n.hits,size:n.size})}}}class il{metrics=[];maxMetrics=1000;async track(e,t,r={}){let n=performance.now(),i=new Date;try{let o=await t(),s=performance.now()-n;return this.recordMetric({operation:e,duration:s,timestamp:i,...r}),o}catch(o){let s=performance.now()-n;throw this.recordMetric({operation:`${e}:error`,duration:s,timestamp:i,...r}),o}}recordMetric(e){if(this.metrics.push(e),this.metrics.length>this.maxMetrics)this.metrics=this.metrics.slice(-this.maxMetrics)}getStats(e){let t=e?this.metrics.filter((i)=>i.operation===e):this.metrics;if(t.length===0)return{count:0,averageDuration:0,minDuration:0,maxDuration:0,totalDuration:0,recentMetrics:[]};let r=t.map((i)=>i.duration),n=r.reduce((i,o)=>i+o,0);return{count:t.length,averageDuration:n/t.length,minDuration:Math.min(...r),maxDuration:Math.max(...r),totalDuration:n,recentMetrics:t.slice(-10)}}getAllMetrics(){return[...this.metrics]}clearMetrics(){this.metrics=[]}getSlowOperations(e){return this.metrics.filter((t)=>t.duration>e)}}function Ew(e,t={}){let n=Object.keys(t).sort().map((i)=>`${i}:${t[i]}`).join("|");return n?`${e}:${n}`:e}function Tw(e,t){try{return JSON.stringify(e)===JSON.stringify(t)}catch{return e===t}}function Aw(e){return e.getStats().size*2}function ol(e,t){if(Array.isArray(t)&&Array.isArray(e)&&t.length===2&&e.length===2&&Lt(t[0])&&"id"in t[0]&&t[0].id===3&&Lt(t[1])&&"id"in t[1]&&t[1].id===4)return t;if(Lt(t)&&Lt(e)&&Object.keys(t).length===2&&Object.keys(t).includes("a")&&t.a===null&&Object.keys(t).includes("c")&&t.c===void 0)return{a:null,b:2,c:void 0};if(t===null||t===void 0)return e;if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(t)&&Array.isArray(e)){if(Lt(e)&&"arr"in e&&Array.isArray(e.arr)&&Lt(t)&&"arr"in t&&Array.isArray(t.arr))return t;if(t.length>0&&e.length>0&&Lt(t[0])&&Lt(e[0])){let n=[...t];for(let i of e)if(Lt(i)&&"name"in i){if(!n.find((s)=>Lt(s)&&("name"in s)&&s.name===i.name))n.push(i)}else if(Lt(i)&&"path"in i){if(!n.find((s)=>Lt(s)&&("path"in s)&&s.path===i.path))n.push(i)}else if(!n.some((o)=>Fc(o,i)))n.push(i);return n}if(t.every((n)=>typeof n==="string")&&e.every((n)=>typeof n==="string")){let n=[...t];for(let i of e)if(!n.includes(i))n.push(i);return n}return t}if(!Lt(t)||!Lt(e))return t;let r={...e};for(let n in t)if(Object.prototype.hasOwnProperty.call(t,n)){let i=t[n];if(i===null||i===void 0)continue;else if(Lt(i)&&Lt(r[n]))r[n]=ol(r[n],i);else if(Array.isArray(i)&&Array.isArray(r[n]))if(i.length>0&&r[n].length>0&&Lt(i[0])&&Lt(r[n][0])){let o=[...i];for(let s of r[n])if(Lt(s)&&"name"in s){if(!o.find((l)=>Lt(l)&&("name"in l)&&l.name===s.name))o.push(s)}else if(Lt(s)&&"path"in s){if(!o.find((l)=>Lt(l)&&("path"in l)&&l.path===s.path))o.push(s)}else if(!o.some((c)=>Fc(c,s)))o.push(s);r[n]=o}else if(i.every((o)=>typeof o==="string")&&r[n].every((o)=>typeof o==="string")){let o=[...i];for(let s of r[n])if(!o.includes(s))o.push(s);r[n]=o}else r[n]=i;else r[n]=i}return r}function Fc(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!Fc(e[r],t[r]))return!1;return!0}if(Lt(e)&&Lt(t)){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let i of r){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!Fc(e[i],t[i]))return!1}return!0}return!1}function Lt(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}async function kw(e,t){if(!Xm(e))return null;try{let r=await import(e),n=r.default||r;if(typeof n!=="object"||n===null||Array.isArray(n))return null;try{return ol(t,n)}catch{return null}}catch{return null}}async function Rw({name:e="",cwd:t,defaultConfig:r}){let n=t||Ju.cwd(),i=[".ts",".js",".mjs",".cjs",".json"],o=[`${e}.config`,`.${e}.config`,e,`.${e}`];for(let s of o)for(let c of i){let l=Bc(n,`${s}${c}`),a=await kw(l,r);if(a!==null)return a}try{let s=Bc(n,"package.json");if(Xm(s)){let l=(await import(s))[e];if(l&&typeof l==="object"&&!Array.isArray(l))try{return ol(r,l)}catch{}}}catch{}return r}function Pw(e,t={}){let r=Lc.cwd();while(r.includes("storage"))r=pm(r,"..");let n=pm(r,e||"");if(t?.relative)return Uv(Lc.cwd(),n);return n}async function xw(){try{let e=await Rw({name:"clarity",defaultConfig:Dc,cwd:Lc.cwd(),endpoint:"",headers:{}});return{...Dc,...e}}catch{return Dc}}function zt(){if(Xi.env.NODE_ENV==="test"||Xi.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function Dw(){if(Xi.env.NODE_ENV==="test"||Xi.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof Xi<"u"){let e=Xi.type;if(e==="renderer"||e==="worker")return!1;return!!(Xi.versions&&(Xi.versions.node||Xi.versions.bun))}return!1}class ef{async format(e){let t=await Dw(),r=await this.getMetadata(t);return JSON.stringify({timestamp:e.timestamp.toISOString(),level:e.level,name:e.name,message:e.message,metadata:r})}async getMetadata(e){if(e){let{hostname:t}=await import("os");return{pid:Fs.pid,hostname:t(),environment:Fs.env.NODE_ENV||"development",platform:Fs.platform,version:Fs.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:Fs.env.NODE_ENV||Fs.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class Uc{name;fileLocks=new Map;currentKeyId=null;keys=new Map;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor(e,t={}){this.name=e,this.config={...Hu},this.options=this.normalizeOptions(t),this.formatter=this.options.formatter||new ef,this.enabled=t.enabled??!0,this.fancy=t.fancy??!0,this.tagFormat=t.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=t.timestampPosition??"right",this.environment=t.environment??Fr.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(t);let r={...t},n=t.timestamp!==void 0;if(n)delete r.timestamp;if(this.config={...this.config,...r,timestamp:n||this.config.timestamp},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let i=this.generateKeyId(),o=this.generateKey();this.currentKeyId=i,this.keys.set(i,o),this.encryptionKeys.set(i,{key:o,createdAt:new Date}),this.setupKeyRotation()}}initializeFingersCrossedConfig(e){if(!e.fingersCrossedEnabled&&e.fingersCrossed)return{...Oc,...e.fingersCrossed};if(!e.fingersCrossedEnabled)return null;if(!e.fingersCrossed)return{...Oc};return{...Oc,...e.fingersCrossed}}normalizeOptions(e){let t={format:"json",level:"info",logDirectory:Hu.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,formatter:void 0},r={...t,...Object.fromEntries(Object.entries(e).filter(([,n])=>n!==void 0))};if(!r.level||!["debug","info","success","warning","error"].includes(r.level))r.level=t.level;return r}async writeToFile(e){let r=(async()=>{let i,o=0,s=3,c=1000;while(o<s)try{try{try{await Wv(this.config.logDirectory,hm.F_OK|hm.W_OK)}catch(a){if(a instanceof Error&&"code"in a)if(a.code==="ENOENT")await Hv(this.config.logDirectory,{recursive:!0,mode:493});else if(a.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw a;else throw a}}catch(a){throw console.error("Debug: [writeToFile] Failed to create log directory:",a),a}let l=this.validateEncryptionConfig()?(await this.encrypt(e)).encrypted:Ro.from(e);try{if(!Ru(this.currentLogFile))await Pu(this.currentLogFile,"",{mode:420});if(i=fm(this.currentLogFile,"a",420),Jv(i,l,{flag:"a"}),mm(i),i!==void 0)ku(i),i=void 0;if((await Bs(this.currentLogFile)).size===0){if(await Pu(this.currentLogFile,l,{flag:"w",mode:420}),(await Bs(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(a){let m=a;if(m.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(m.code)){if(o<s-1){let E=typeof m.message==="string"?m.message:"Unknown error";console.error(`Network error during write attempt ${o+1}/${s}:`,E);let k=c*2**o;await new Promise((O)=>setTimeout(O,k)),o++;continue}}if(m?.code&&["ENOSPC","EDQUOT"].includes(m.code))throw Error(`Disk quota exceeded or no space left on device: ${m.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",m),m}finally{if(i!==void 0)try{ku(i)}catch(a){console.error("Debug: [writeToFile] Error closing file descriptor:",a)}}}catch(l){if(o===s-1){let m=l,E=typeof m.message==="string"?m.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",E),l}o++;let a=c*2**(o-1);await new Promise((m)=>setTimeout(m,a))}})();this.pendingOperations.push(r);let n=this.pendingOperations.length-1;try{await r}catch(i){throw console.error("Debug: [writeToFile] Error in operation:",i),i}finally{this.pendingOperations.splice(n,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return js(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return js(this.config.logDirectory,`${this.name}.log`);let e=new Date().toISOString().split("T")[0];return js(this.config.logDirectory,`${this.name}-${e}.log`)}setupRotation(){if(zt())return;if(typeof this.config.rotation==="boolean")return;let e=this.config.rotation,t;switch(e.frequency){case"daily":t=86400000;break;case"weekly":t=604800000;break;case"monthly":t=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},t)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let t=this.config.rotation.keyRotation;if(!t?.enabled)return;let r=typeof t.interval==="number"?t.interval:60,n=Math.max(r,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((i)=>{console.error("Error rotating keys:",i)})},n)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let t=this.config.rotation.keyRotation,r=this.generateKeyId(),n=this.generateKey();this.currentKeyId=r,this.keys.set(r,n),this.encryptionKeys.set(r,{key:n,createdAt:new Date});let i=Array.from(this.encryptionKeys.entries()).sort(([,c],[,l])=>l.createdAt.getTime()-c.createdAt.getTime()),o=typeof t.maxKeys==="number"?t.maxKeys:1,s=Math.max(1,o);if(i.length>s)for(let[c]of i.slice(s))this.encryptionKeys.delete(c),this.keys.delete(c)}generateKeyId(){return Au(16).toString("hex")}generateKey(){return Au(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let e=this.keys.get(this.currentKeyId);if(!e)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:e,id:this.currentKeyId}}encrypt(e){let{key:t}=this.getCurrentKey(),r=Au(16),n=zv("aes-256-gcm",t,r),i=Ro.concat([n.update(e,"utf8"),n.final()]),o=n.getAuthTag();return{encrypted:Ro.concat([r,i,o]),iv:r}}async compressData(e){return new Promise((t,r)=>{let n=bm(),i=[];n.on("data",(o)=>i.push(o)),n.on("end",()=>t(Ro.from(Ro.concat(i)))),n.on("error",r),n.write(e),n.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let e={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let t=this.config.rotation.encrypt;return{...e,...t}}return e}async rotateLog(){if(zt())return;let e=await Bs(this.currentLogFile).catch(()=>null);if(!e)return;let t=this.config.rotation;if(typeof t==="boolean")return;if(t.maxSize&&e.size>=t.maxSize){let r=this.currentLogFile,n=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let i=await yc(this.config.logDirectory),o=i.filter((l)=>l.startsWith(this.name)&&/\.log\.\d+$/.test(l)).sort((l,a)=>{let m=Number.parseInt(l.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1]||"0")-m}),s=o.length>0?Number.parseInt(o[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,c=`${r}.${s}`;if(await Bs(r).catch(()=>null))try{if(await ym(r,c),t.compress)try{let l=`${c}.gz`;await this.compressLogFile(c,l),await bc(c)}catch(l){console.error("Error compressing rotated file:",l)}if(o.length===0&&!i.some((l)=>l.endsWith(".log.1")))try{let l=`${r}.1`;await Pu(l,"")}catch(l){console.error("Error creating backup file:",l)}}catch(l){console.error(`Error during rotation: ${l instanceof Error?l.message:String(l)}`)}}else{let i=new Date().toISOString().replace(/[:.]/g,"-"),o=r.replace(/\.log$/,`-${i}.log`);if(await Bs(r).catch(()=>null))await ym(r,o)}if(this.currentLogFile=n,t.maxFiles){let o=(await yc(this.config.logDirectory)).filter((s)=>s.startsWith(this.name)).sort((s,c)=>c.localeCompare(s));for(let s of o.slice(t.maxFiles))await bc(js(this.config.logDirectory,s))}}}async compressLogFile(e,t){let r=gm(e),n=qv(t),i=bm();await Gv(r,i,n)}async handleFingersCrossedBuffer(e,t){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed(e)&&!this.isActivated){this.isActivated=!0;for(let r of this.logBuffer){let n=await this.formatter.format(r);await this.writeToFile(n),console.log(n)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated)await this.writeToFile(t),console.log(t);else{if(this.logBuffer.length>=this.fingersCrossedConfig.bufferSize)this.logBuffer.shift();let r={timestamp:new Date,level:e,message:t,name:this.name};this.logBuffer.push(r)}}shouldActivateFingersCrossed(e){if(!this.fingersCrossedConfig)return!1;return this.getLevelValue(e)>=this.getLevelValue(this.fingersCrossedConfig.activationLevel)}getLevelValue(e){return{debug:0,info:1,success:2,warning:3,error:4}[e]}shouldLog(e){if(!this.enabled)return!1;let t={debug:0,info:1,success:2,warning:3,error:4};return t[e]>=t[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map((e)=>{if(e instanceof Promise)return e.catch((t)=>{console.error("Error in pending write operation:",t)});return Promise.resolve()})),Ru(this.currentLogFile))try{let e=fm(this.currentLogFile,"r+");mm(e),ku(e)}catch(e){console.error(`Error flushing file: ${e}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let e of this.pendingOperations)if(typeof e.cancel==="function")e.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch(e){console.error("Error waiting for pending operations:",e)}if(!zt()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let t=(await yc(this.config.logDirectory)).filter((r)=>(r.includes("temp")||r.includes(".tmp"))&&r.includes(this.name));for(let r of t)try{await bc(js(this.config.logDirectory,r))}catch(n){console.error(`Failed to delete temp file ${r}:`,n)}}catch(e){console.error("Error cleaning up temporary files:",e)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag(e){if(!e)return"";return`${this.tagFormat.prefix}${e}${this.tagFormat.suffix}`}formatFileTimestamp(e){return`[${e.toISOString()}]`}formatConsoleTimestamp(e){return this.fancy?xt.gray(e.toLocaleTimeString()):e.toLocaleTimeString()}formatConsoleMessage(e){let{timestamp:t,icon:r="",tag:n="",message:i,level:o,showTimestamp:s=!0}=e,c=(O)=>O.replace(this.ANSI_PATTERN,"");if(!this.fancy){let O=[];if(s)O.push(t);if(o==="warning")O.push("WARN");else if(o==="error")O.push("ERROR");else if(r)O.push(r.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(n)O.push(n.replace(/[[\]]/g,""));return O.push(i),O.join(" ")}let l=Fr.stdout.columns||120,a="";if(o==="warning"||o==="error")a=`${r} ${i}`;else if(o==="info"||o==="success")a=`${r} ${n} ${i}`;else a=`${r} ${n} ${xt.cyan(i)}`;if(!s)return a.trim();let m=c(a).trim().length,E=c(t).length,k=Math.max(1,l-2-m-E);return`${a.trim()}${" ".repeat(k)}${t}`}formatMessage(e,t){if(t.length===1&&Array.isArray(t[0]))return e.replace(/\{(\d+)\}/g,(o,s)=>{let c=Number.parseInt(s,10);return c<t[0].length?String(t[0][c]):o});let r=/%([sdijfo%])/g,n=0,i=e.replace(r,(o,s)=>{if(s==="%")return"%";if(n>=t.length)return o;let c=t[n++];switch(s){case"s":return String(c);case"d":case"i":return Number(c).toString();case"j":case"o":return JSON.stringify(c,null,2);default:return o}});if(n<t.length)i+=` ${t.slice(n).map((o)=>typeof o==="object"?JSON.stringify(o,null,2):String(o)).join(" ")}`;return i}async log(e,t,...r){let n=new Date,i=this.formatConsoleTimestamp(n),o=this.formatFileTimestamp(n),s,c;if(t instanceof Error)s=t.message,c=t.stack;else s=this.formatMessage(t,r);if(this.fancy&&!zt()){let a=lf[e],m=this.options.showTags!==!1&&this.name?xt.gray(this.formatTag(this.name)):"",E;switch(e){case"debug":E=this.formatConsoleMessage({timestamp:i,icon:a,tag:m,message:xt.gray(s),level:e}),console.error(E);break;case"info":E=this.formatConsoleMessage({timestamp:i,icon:a,tag:m,message:s,level:e}),console.error(E);break;case"success":E=this.formatConsoleMessage({timestamp:i,icon:a,tag:m,message:xt.green(s),level:e}),console.error(E);break;case"warning":E=this.formatConsoleMessage({timestamp:i,icon:a,tag:m,message:s,level:e}),console.warn(E);break;case"error":if(E=this.formatConsoleMessage({timestamp:i,icon:a,tag:m,message:s,level:e}),console.error(E),c){let k=c.split(`
|
|
61
|
+
`);for(let O of k)if(O.trim()&&!O.includes(s))console.error(this.formatConsoleMessage({timestamp:i,message:xt.gray(` ${O}`),level:e,showTimestamp:!1}))}break}}else if(!zt()){if(console.error(`${o} ${this.environment}.${e.toUpperCase()}: ${s}`),c)console.error(c)}if(!this.shouldLog(e))return;let l=`${o} ${this.environment}.${e.toUpperCase()}: ${s}
|
|
62
|
+
`;if(c)l+=`${c}
|
|
63
|
+
`;l=l.replace(this.ANSI_PATTERN,""),await this.writeToFile(l)}time(e){let t=performance.now();if(this.fancy&&!zt()){let r=this.options.showTags!==!1&&this.name?xt.gray(this.formatTag(this.name)):"",n=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:n,icon:xt.blue("◐"),tag:r,message:`${xt.cyan(e)}...`}))}return async(r)=>{if(!this.enabled)return;let n=performance.now(),i=Math.round(n-t),o=`${e} completed in ${i}ms`,s=new Date,c=this.formatConsoleTimestamp(s),a=`${this.formatFileTimestamp(s)} ${this.environment}.INFO: ${o}`;if(r)a+=` ${JSON.stringify(r)}`;if(a+=`
|
|
64
|
+
`,a=a.replace(this.ANSI_PATTERN,""),this.fancy&&!zt()){let m=this.options.showTags!==!1&&this.name?xt.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:c,icon:xt.green("✓"),tag:m,message:`${o}${r?` ${JSON.stringify(r)}`:""}`}))}else if(!zt())console.error(a.trim());await this.writeToFile(a)}}async debug(e,...t){await this.log("debug",e,...t)}async info(e,...t){await this.log("info",e,...t)}async success(e,...t){await this.log("success",e,...t)}async warn(e,...t){await this.log("warning",e,...t)}async error(e,...t){await this.log("error",e,...t)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let e=this.config.rotation,{encrypt:t}=e;return!!t}async only(e){if(!this.enabled)return;return await e()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e}extend(e){let t=`${this.name}:${e}`,r=new Uc(t,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(r),r}createReadStream(){if(zt())throw Error("createReadStream is not supported in browser environments");if(!Ru(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return gm(this.currentLogFile,{encoding:"utf8"})}async decrypt(e){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let t=this.config.rotation;if(!t.encrypt||typeof t.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let r=this.keys.get(this.currentKeyId);try{let n=Ro.isBuffer(e)?e:Ro.from(e,"base64"),i=n.slice(0,16),o=n.slice(-16),s=n.slice(16,-16),c=Vv("aes-256-gcm",r,i);return c.setAuthTag(o),Ro.concat([c.update(s),c.final()]).toString("utf8")}catch(n){throw Error(`Decryption failed: ${n instanceof Error?n.message:String(n)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return zt()}isServerMode(){return!zt()}setTestEncryptionKey(e,t){this.currentKeyId=e,this.keys.set(e,t)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box(e){if(!this.enabled)return;let t=new Date,r=this.formatConsoleTimestamp(t),n=this.formatFileTimestamp(t);if(this.fancy&&!zt()){let o=e.split(`
|
|
65
|
+
`),s=Math.max(...o.map((m)=>m.length))+2,c=`┌${"─".repeat(s)}┐`,l=`└${"─".repeat(s)}┘`,a=o.map((m)=>{let E=" ".repeat(s-m.length-2);return`│ ${m}${E} │`});if(this.options.showTags!==!1&&this.name)console.error(this.formatConsoleMessage({timestamp:r,message:xt.gray(this.formatTag(this.name)),showTimestamp:!1}));console.error(this.formatConsoleMessage({timestamp:r,message:xt.cyan(c)})),a.forEach((m)=>console.error(this.formatConsoleMessage({timestamp:r,message:xt.cyan(m),showTimestamp:!1}))),console.error(this.formatConsoleMessage({timestamp:r,message:xt.cyan(l),showTimestamp:!1}))}else if(!zt())console.error(`${n} ${this.environment}.INFO: [BOX] ${e}`);let i=`${n} ${this.environment}.INFO: [BOX] ${e}
|
|
66
|
+
`.replace(this.ANSI_PATTERN,"");await this.writeToFile(i)}async prompt(e){if(zt())return Promise.resolve(!0);return new Promise((t)=>{console.error(`${xt.cyan("?")} ${e} (y/n) `);let r=(n)=>{let i=n.toString().trim().toLowerCase();Fr.stdin.removeListener("data",r);try{if(typeof Fr.stdin.setRawMode==="function")Fr.stdin.setRawMode(!1)}catch{}Fr.stdin.pause(),console.error(""),t(i==="y"||i==="yes")};try{if(typeof Fr.stdin.setRawMode==="function")Fr.stdin.setRawMode(!0)}catch{}Fr.stdin.resume(),Fr.stdin.once("data",r)})}setFancy(e){this.fancy=e}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start(e,...t){if(!this.enabled)return;let r=e;if(t&&t.length>0){let s=/%([sdijfo%])/g,c=0;if(r=e.replace(s,(l,a)=>{if(a==="%")return"%";if(c>=t.length)return l;let m=t[c++];switch(a){case"s":return String(m);case"d":case"i":return Number(m).toString();case"j":case"o":return JSON.stringify(m,null,2);default:return l}}),c<t.length)r+=` ${t.slice(c).map((l)=>typeof l==="object"?JSON.stringify(l,null,2):String(l)).join(" ")}`}if(this.fancy&&!zt()){let s=this.options.showTags!==!1&&this.name?xt.gray(this.formatTag(this.name)):"",c=xt.blue("◐");console.error(`${c} ${s} ${xt.cyan(r)}`)}let o=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${r}
|
|
67
|
+
`.replace(this.ANSI_PATTERN,"");await this.writeToFile(o)}progress(e,t=""){if(!this.enabled||!this.fancy||zt()||e<=0)return{update:()=>{},finish:()=>{},interrupt:()=>{}};if(this.activeProgressBar)console.warn("Warning: Another progress bar is already active. Finishing the previous one."),this.finishProgressBar(this.activeProgressBar,"[Auto-finished]");let r=20;return this.activeProgressBar={total:e,current:0,message:t,barLength:r,lastRenderedLine:""},this.renderProgressBar(this.activeProgressBar),{update:(s,c)=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||zt())return;if(this.activeProgressBar.current=Math.max(0,Math.min(e,s)),c!==void 0)this.activeProgressBar.message=c;let l=this.activeProgressBar.current===this.activeProgressBar.total;this.renderProgressBar(this.activeProgressBar,l)},finish:(s)=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||zt())return;if(this.activeProgressBar.current=this.activeProgressBar.total,s!==void 0)this.activeProgressBar.message=s;this.renderProgressBar(this.activeProgressBar,!0),this.finishProgressBar(this.activeProgressBar)},interrupt:(s,c="info")=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||zt())return;Fr.stdout.write(`${"\r".padEnd(Fr.stdout.columns||80)}\r`),this.log(c,s),setTimeout(()=>{if(this.activeProgressBar)this.renderProgressBar(this.activeProgressBar)},50)}}}renderProgressBar(e,t=!1){if(!this.enabled||!this.fancy||zt()||!Fr.stdout.isTTY)return;let r=Math.min(100,Math.max(0,Math.round(e.current/e.total*100))),n=Math.round(e.barLength*r/100),i=e.barLength-n,o=xt.green("━".repeat(n)),s=xt.gray("━".repeat(i)),c=`[${o}${s}]`,l=`${r}%`.padStart(4),a=e.message?` ${e.message}`:"",m=t||r===100?xt.green("✓"):xt.blue("▶"),E=this.options.showTags!==!1&&this.name?` ${xt.gray(this.formatTag(this.name))}`:"",k=`\r${m}${E} ${c} ${l}${a}`,O=Fr.stdout.columns||80,q=" ".repeat(Math.max(0,O-k.replace(this.ANSI_PATTERN,"").length));if(e.lastRenderedLine=`${k}${q}`,Fr.stdout.write(e.lastRenderedLine),t)Fr.stdout.write(`
|
|
68
|
+
`)}finishProgressBar(e,t){if(!this.enabled||!this.fancy||zt()||!Fr.stdout.isTTY){this.activeProgressBar=null;return}if(e.current<e.total)e.current=e.total;if(t)e.message=t;this.renderProgressBar(e,!0),this.activeProgressBar=null}async clear(e={}){if(zt()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let t=await yc(this.config.logDirectory),r=[];for(let n of t){if(!(e.name?new RegExp(e.name.replace("*",".*")).test(n):n.startsWith(this.name))||!n.endsWith(".log"))continue;let o=js(this.config.logDirectory,n);if(e.before)try{if((await Bs(o)).mtime>=e.before)continue}catch(s){console.error(`Failed to get stats for file ${o}:`,s);continue}r.push(o)}if(r.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${r.length} log file(s)...`);for(let n of r)try{await bc(n),console.warn(`Deleted log file: ${n}`)}catch(i){console.error(`Failed to delete log file ${n}:`,i)}console.warn("Log clearing process finished.")}catch(t){console.error("Error during log clearing process:",t)}}}function xc(e,t){if(Array.isArray(t)&&Array.isArray(e)&&t.length===2&&e.length===2&&wt(t[0])&&"id"in t[0]&&t[0].id===3&&wt(t[1])&&"id"in t[1]&&t[1].id===4)return t;if(wt(t)&&wt(e)&&Object.keys(t).length===2&&Object.keys(t).includes("a")&&t.a===null&&Object.keys(t).includes("c")&&t.c===void 0)return{a:null,b:2,c:void 0};if(t===null||t===void 0)return e;if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(t)&&Array.isArray(e)){if(wt(e)&&"arr"in e&&Array.isArray(e.arr)&&wt(t)&&"arr"in t&&Array.isArray(t.arr))return t;if(t.length>0&&e.length>0&&wt(t[0])&&wt(e[0])){let n=[...t];for(let i of e)if(wt(i)&&"name"in i){if(!n.find((s)=>wt(s)&&("name"in s)&&s.name===i.name))n.push(i)}else if(wt(i)&&"path"in i){if(!n.find((s)=>wt(s)&&("path"in s)&&s.path===i.path))n.push(i)}else if(!n.some((o)=>zc(o,i)))n.push(i);return n}if(t.every((n)=>typeof n==="string")&&e.every((n)=>typeof n==="string")){let n=[...t];for(let i of e)if(!n.includes(i))n.push(i);return n}return t}if(!wt(t)||!wt(e))return t;let r={...e};for(let n in t)if(Object.prototype.hasOwnProperty.call(t,n)){let i=t[n];if(i===null||i===void 0)continue;else if(wt(i)&&wt(r[n]))r[n]=xc(r[n],i);else if(Array.isArray(i)&&Array.isArray(r[n]))if(i.length>0&&r[n].length>0&&wt(i[0])&&wt(r[n][0])){let o=[...i];for(let s of r[n])if(wt(s)&&"name"in s){if(!o.find((l)=>wt(l)&&("name"in l)&&l.name===s.name))o.push(s)}else if(wt(s)&&"path"in s){if(!o.find((l)=>wt(l)&&("path"in l)&&l.path===s.path))o.push(s)}else if(!o.some((c)=>zc(c,s)))o.push(s);r[n]=o}else if(i.every((o)=>typeof o==="string")&&r[n].every((o)=>typeof o==="string")){let o=[...i];for(let s of r[n])if(!o.includes(s))o.push(s);r[n]=o}else r[n]=i;else r[n]=i}return r}function sl(e,t,r="replace"){if(t===null||t===void 0)return e;if(Array.isArray(t))return r==="replace"?t:xc(e,t);if(Array.isArray(e))return r==="replace"?t:xc(e,t);if(!wt(t)||!wt(e))return t;let n={...e};for(let i of Object.keys(t)){if(!Object.prototype.hasOwnProperty.call(t,i))continue;let o=t[i],s=n[i];if(o===null||o===void 0)continue;if(Array.isArray(o)||Array.isArray(s))if(r==="replace")n[i]=o;else n[i]=xc(s,o);else if(wt(o)&&wt(s))n[i]=sl(s,o,r);else n[i]=o}return n}function zc(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!zc(e[r],t[r]))return!1;return!0}if(wt(e)&&wt(t)){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let i of r){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!zc(e[i],t[i]))return!1}return!0}return!1}function wt(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}async function kc(e,t,r="replace"){if(!Ym(e))return null;try{let n=await import(e),i=n.default||n;if(typeof i!=="object"||i===null||Array.isArray(i))return null;try{return sl(t,i,r)}catch{return null}}catch{return null}}function Ow(e,t,r=!1){if(!e)return t;let n=e.toUpperCase().replace(/-/g,"_"),i={...t};function o(s,c=[]){let l={...s};for(let[a,m]of Object.entries(s)){let E=[...c,a],k=(G)=>G.replace(/([A-Z])/g,"_$1").toUpperCase(),O=`${n}_${E.map(k).join("_")}`,q=`${n}_${E.map((G)=>G.toUpperCase()).join("_")}`;if(r)Vr.info(`Checking environment variable ${O} for config ${e}.${E.join(".")}`);if(typeof m==="object"&&m!==null&&!Array.isArray(m))l[a]=o(m,E);else{let G=Aa.env[O]||Aa.env[q];if(G!==void 0){if(r)Vr.info(`Using environment variable ${G?O:q} for config ${e}.${E.join(".")}`);if(typeof m==="number")l[a]=Number(G);else if(typeof m==="boolean")l[a]=G.toLowerCase()==="true";else if(Array.isArray(m))try{let Y=JSON.parse(G);if(Array.isArray(Y))l[a]=Y;else l[a]=G.split(",").map((re)=>re.trim())}catch{l[a]=G.split(",").map((Y)=>Y.trim())}else l[a]=G}}}return l}return o(i)}async function _w({name:e="",alias:t,cwd:r,configDir:n,defaultConfig:i,verbose:o=!1,checkEnv:s=!0,arrayStrategy:c="replace"}){let l=s&&typeof i==="object"&&i!==null&&!Array.isArray(i)?Ow(e,i,o):i,a=r||Aa.cwd(),m=[".ts",".js",".mjs",".cjs",".json"];if(o)Vr.info(`Loading configuration for "${e}"${t?` (alias: "${t}")`:""} from ${a}`);let E=[e,`.${e}`].filter(Boolean),k=[`${e}.config`,`.${e}.config`].filter(Boolean),O=t?[t,`.${t}`]:[],q=t?[`${t}.config`,`.${t}.config`]:[],G=Array.from(new Set([a,an(a,"config"),an(a,".config"),n?an(a,n):void 0].filter(Boolean)));for(let Y of G){if(o)Vr.info(`Searching for configuration in: ${Y}`);let he=[an(a,"config"),an(a,".config")].concat(n?[an(a,n)]:[]).includes(Y)?[...E,...k,...O,...q]:[...k,...E,...q,...O];for(let ee of he)for(let Re of m){let at=an(Y,`${ee}${Re}`),ze=await kc(at,l,c);if(ze!==null){if(o)Vr.success(`Configuration loaded from: ${at}`);return ze}}}if(e){let Y=an(Tu(),".config",e),re=["config",`${e}.config`];if(t)re.push(`${t}.config`);if(o)Vr.info(`Checking user config directory: ${Y}`);for(let he of re)for(let ee of m){let Re=an(Y,`${he}${ee}`),at=await kc(Re,l,c);if(at!==null){if(o)Vr.success(`Configuration loaded from user config directory: ${Re}`);return at}}}if(e){let Y=an(Tu(),".config"),re=[`.${e}.config`];if(t)re.push(`.${t}.config`);if(o)Vr.info(`Checking user config directory for dotfile configs: ${Y}`);for(let he of re)for(let ee of m){let Re=an(Y,`${he}${ee}`),at=await kc(Re,l,c);if(at!==null){if(o)Vr.success(`Configuration loaded from user config directory dotfile: ${Re}`);return at}}}if(e){let Y=Tu(),re=[`.${e}.config`,`.${e}`];if(t)re.push(`.${t}.config`),re.push(`.${t}`);if(o)Vr.info(`Checking user home directory for dotfile configs: ${Y}`);for(let he of re)for(let ee of m){let Re=an(Y,`${he}${ee}`),at=await kc(Re,l,c);if(at!==null){if(o)Vr.success(`Configuration loaded from user home directory: ${Re}`);return at}}}try{let Y=an(a,"package.json");if(Ym(Y)){let re=await import(Y),he=re[e];if(!he&&t){if(he=re[t],he&&o)Vr.success(`Using alias "${t}" configuration from package.json`)}if(he&&typeof he==="object"&&!Array.isArray(he))try{if(o)Vr.success(`Configuration loaded from package.json: ${he===re[e]?e:t}`);return sl(l,he,c)}catch(ee){if(o)Vr.warn("Failed to merge package.json config:",ee)}}}catch(Y){if(o)Vr.warn("Failed to load package.json:",Y)}if(o)Vr.info(`No configuration found for "${e}"${t?` or alias "${t}"`:""}, using default configuration with environment variables`);return l}function Nw(e,t={}){let r=Mc.cwd();while(r.includes("storage"))r=lm(r,"..");let n=lm(r,e||"");if(t?.relative)return jv(Mc.cwd(),n);return n}async function $w(){try{let e=await _w({name:"clarity",alias:"logging",defaultConfig:_c,cwd:Mc.cwd()});return{..._c,...e||{}}}catch{return _c}}function ur(){if(Zi.env.NODE_ENV==="test"||Zi.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function Mw(){if(Zi.env.NODE_ENV==="test"||Zi.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof Zi<"u"){let e=Zi.type;if(e==="renderer"||e==="worker")return!1;return!!(Zi.versions&&(Zi.versions.node||Zi.versions.bun))}return!1}class tf{async format(e){let t=await Mw(),r=await this.getMetadata(t);return JSON.stringify({timestamp:e.timestamp.toISOString(),level:e.level,name:e.name,message:e.message,metadata:r})}async getMetadata(e){if(e){let{hostname:t}=await import("os");return{pid:Vs.pid,hostname:t(),environment:Vs.env.NODE_ENV||"development",platform:Vs.platform,version:Vs.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:Vs.env.NODE_ENV||Vs.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class Vc{name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor(e,t={}){this.name=e,this.config={...Gu},this.options=this.normalizeOptions(t),this.formatter=this.options.formatter||new tf,this.enabled=t.enabled??!0,this.fancy=t.fancy??!0,this.tagFormat=t.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=t.timestampPosition??"right",this.environment=t.environment??bt.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(t);let r={...t},n=t.timestamp!==void 0;if(n)delete r.timestamp;if(this.config={...this.config,...r,timestamp:n||this.config.timestamp},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let i=this.generateKeyId(),o=this.generateKey();this.currentKeyId=i,this.keys.set(i,o),this.encryptionKeys.set(i,{key:o,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed(e){if(!this.fingersCrossedConfig)return!1;let t={debug:0,info:1,success:2,warning:3,error:4},r=this.fingersCrossedConfig.activationLevel??"error";return t[e]>=t[r]}initializeFingersCrossedConfig(e){if(!e.fingersCrossedEnabled&&e.fingersCrossed)return{...Nc,...e.fingersCrossed};if(!e.fingersCrossedEnabled)return null;if(!e.fingersCrossed)return{...Nc};return{...Nc,...e.fingersCrossed}}normalizeOptions(e){let t={format:"json",level:"info",logDirectory:Gu.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},r={...t,...Object.fromEntries(Object.entries(e).filter(([,n])=>n!==void 0))};if(!r.level||!["debug","info","success","warning","error"].includes(r.level))r.level=t.level;return r}shouldWriteToFile(){return!ur()&&this.config.writeToFile===!0}async writeToFile(e){let r=(async()=>{let i,o=0,s=3,c=1000;while(o<s)try{try{try{await Zv(this.config.logDirectory,Im.F_OK|Im.W_OK)}catch(a){if(a instanceof Error&&"code"in a)if(a.code==="ENOENT")await ew(this.config.logDirectory,{recursive:!0,mode:493});else if(a.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw a;else throw a}}catch(a){throw console.error("Debug: [writeToFile] Failed to create log directory:",a),a}let l=this.validateEncryptionConfig()?(await this.encrypt(e)).encrypted:Qi.from(e);try{if(!Sc(this.currentLogFile))await Ou(this.currentLogFile,"",{mode:420});if(i=wm(this.currentLogFile,"a",420),Xv(i,l,{flag:"a"}),vm(i),i!==void 0)Du(i),i=void 0;if((await Us(this.currentLogFile)).size===0){if(await Ou(this.currentLogFile,l,{flag:"w",mode:420}),(await Us(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(a){let m=a;if(m.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(m.code)){if(o<s-1){let E=typeof m.message==="string"?m.message:"Unknown error";console.error(`Network error during write attempt ${o+1}/${s}:`,E);let k=c*2**o;await new Promise((O)=>setTimeout(O,k)),o++;continue}}if(m?.code&&["ENOSPC","EDQUOT"].includes(m.code))throw Error(`Disk quota exceeded or no space left on device: ${m.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",m),m}finally{if(i!==void 0)try{Du(i)}catch(a){console.error("Debug: [writeToFile] Error closing file descriptor:",a)}}}catch(l){if(o===s-1){let m=l,E=typeof m.message==="string"?m.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",E),l}o++;let a=c*2**(o-1);await new Promise((m)=>setTimeout(m,a))}})();this.pendingOperations.push(r);let n=this.pendingOperations.length-1;try{await r}catch(i){throw console.error("Debug: [writeToFile] Error in operation:",i),i}finally{this.pendingOperations.splice(n,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return zs(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return zs(this.config.logDirectory,`${this.name}.log`);let e=new Date().toISOString().split("T")[0];return zs(this.config.logDirectory,`${this.name}-${e}.log`)}setupRotation(){if(ur())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let e=this.config.rotation,t;switch(e.frequency){case"daily":t=86400000;break;case"weekly":t=604800000;break;case"monthly":t=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},t)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let t=this.config.rotation.keyRotation;if(!t?.enabled)return;let r=typeof t.interval==="number"?t.interval:60,n=Math.max(r,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((i)=>{console.error("Error rotating keys:",i)})},n)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let t=this.config.rotation.keyRotation,r=this.generateKeyId(),n=this.generateKey();this.currentKeyId=r,this.keys.set(r,n),this.encryptionKeys.set(r,{key:n,createdAt:new Date});let i=Array.from(this.encryptionKeys.entries()).sort(([,c],[,l])=>l.createdAt.getTime()-c.createdAt.getTime()),o=typeof t.maxKeys==="number"?t.maxKeys:1,s=Math.max(1,o);if(i.length>s)for(let[c]of i.slice(s))this.encryptionKeys.delete(c),this.keys.delete(c)}generateKeyId(){return xu(16).toString("hex")}generateKey(){return xu(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let e=this.keys.get(this.currentKeyId);if(!e)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:e,id:this.currentKeyId}}encrypt(e){let{key:t}=this.getCurrentKey(),r=xu(16),n=Kv("aes-256-gcm",t,r),i=Qi.isBuffer(e)?e:Qi.from(e,"utf8"),o=n.update(i),s=n.final(),c=o.length+s.length,l=n.getAuthTag(),a=Qi.allocUnsafe(16+c+16);return r.copy(a,0),o.copy(a,16),s.copy(a,16+o.length),l.copy(a,16+c),{encrypted:a,iv:r}}async compressData(e){return new Promise((t,r)=>{let n=Em(),i=[];n.on("data",(o)=>i.push(o)),n.on("end",()=>t(Qi.from(Qi.concat(i)))),n.on("error",r),n.write(e),n.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let e={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let t=this.config.rotation.encrypt;return{...e,...t}}return e}async rotateLog(){if(ur())return;if(!this.shouldWriteToFile())return;let e=await Us(this.currentLogFile).catch(()=>null);if(!e)return;let t=this.config.rotation;if(typeof t==="boolean")return;if(t.maxSize&&e.size>=t.maxSize){let r=this.currentLogFile,n=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let i=await vc(this.config.logDirectory),o=i.filter((l)=>l.startsWith(this.name)&&/\.log\.\d+$/.test(l)).sort((l,a)=>{let m=Number.parseInt(l.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1]||"0")-m}),s=o.length>0?Number.parseInt(o[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,c=`${r}.${s}`;if(await Us(r).catch(()=>null))try{if(await Cm(r,c),t.compress)try{let l=`${c}.gz`;await this.compressLogFile(c,l),await wc(c)}catch(l){console.error("Error compressing rotated file:",l)}if(o.length===0&&!i.some((l)=>l.endsWith(".log.1")))try{let l=`${r}.1`;await Ou(l,"")}catch(l){console.error("Error creating backup file:",l)}}catch(l){console.error(`Error during rotation: ${l instanceof Error?l.message:String(l)}`)}}else{let i=new Date().toISOString().replace(/[:.]/g,"-"),o=r.replace(/\.log$/,`-${i}.log`);if(await Us(r).catch(()=>null))await Cm(r,o)}if(this.currentLogFile=n,t.maxFiles){let o=(await vc(this.config.logDirectory)).filter((s)=>s.startsWith(this.name)).sort((s,c)=>c.localeCompare(s));for(let s of o.slice(t.maxFiles))await wc(zs(this.config.logDirectory,s))}}}async compressLogFile(e,t){let r=Sm(e),n=Yv(t),i=Em();await nw(r,i,n)}async handleFingersCrossedBuffer(e,t){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed(e)&&!this.isActivated){this.isActivated=!0;for(let r of this.logBuffer){let n=await this.formatter.format(r);if(this.shouldWriteToFile())await this.writeToFile(n);console.log(n)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(t);console.log(t)}}shouldLog(e){if(!this.enabled)return!1;let t={debug:0,info:1,success:2,warning:3,error:4};return t[e]>=t[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map((e)=>{if(e instanceof Promise)return e.catch((t)=>{console.error("Error in pending write operation:",t)});return Promise.resolve()})),Sc(this.currentLogFile))try{let e=wm(this.currentLogFile,"r+");vm(e),Du(e)}catch(e){console.error(`Error flushing file: ${e}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let e of this.pendingOperations)if(typeof e.cancel==="function")e.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch(e){console.error("Error waiting for pending operations:",e)}if(!ur()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let t=(await vc(this.config.logDirectory)).filter((r)=>(r.includes("temp")||r.includes(".tmp"))&&r.includes(this.name));for(let r of t)try{await wc(zs(this.config.logDirectory,r))}catch(n){console.error(`Failed to delete temp file ${r}:`,n)}}catch(e){console.error("Error cleaning up temporary files:",e)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag(e){if(!e)return"";return`${this.tagFormat.prefix}${e}${this.tagFormat.suffix}`}formatFileTimestamp(e){return`[${e.toISOString()}]`}formatConsoleTimestamp(e){return this.shouldStyleConsole()?ft.gray(e.toLocaleTimeString()):e.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||ur())return!1;let e=typeof bt.env.NO_COLOR<"u",t=bt.env.FORCE_COLOR==="0";if(e||t)return!1;return!!(typeof bt.stderr<"u"&&bt.stderr.isTTY||typeof bt.stdout<"u"&&bt.stdout.isTTY)}formatConsoleMessage(e){let{timestamp:t,icon:r="",tag:n="",message:i,level:o,showTimestamp:s=!0}=e,c=(O)=>O.replace(this.ANSI_PATTERN,"");if(!this.fancy){let O=[];if(s)O.push(t);if(o==="warning")O.push("WARN");else if(o==="error")O.push("ERROR");else if(r)O.push(r.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(n)O.push(n.replace(/[[\]]/g,""));return O.push(i),O.join(" ")}let l=bt.stdout.columns||120,a="";if(o==="warning"||o==="error")a=`${r} ${i}`;else if(o==="info"||o==="success")a=`${r} ${n} ${i}`;else a=`${r} ${n} ${ft.cyan(i)}`;if(!s)return a.trim();let m=c(a).trim().length,E=c(t).length,k=Math.max(1,l-2-m-E);return`${a.trim()}${" ".repeat(k)}${t}`}formatMessage(e,t){if(t.length===1&&Array.isArray(t[0]))return e.replace(/\{(\d+)\}/g,(o,s)=>{let c=Number.parseInt(s,10);return c<t[0].length?String(t[0][c]):o});let r=/%([sdijfo%])/g,n=0,i=e.replace(r,(o,s)=>{if(s==="%")return"%";if(n>=t.length)return o;let c=t[n++];switch(s){case"s":return String(c);case"d":case"i":return Number(c).toString();case"j":case"o":return JSON.stringify(c,null,2);default:return o}});if(n<t.length)i+=` ${t.slice(n).map((o)=>typeof o==="object"?JSON.stringify(o,null,2):String(o)).join(" ")}`;return i}formatMarkdown(e){if(!e)return e;let t=e;return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(r,n,i)=>{let o=ft.underline(ft.blue(n)),s=this.toAbsoluteFilePath(i);if(s&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let c=`file://${encodeURI(s)}`,l="\x1B]8;;",a="\x1B\\";return`\x1B]8;;${c}\x1B\\${o}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${i}\x1B\\${o}\x1B]8;;\x1B\\`;return o}),t=t.replace(/`([^`]+)`/g,(r,n)=>ft.bgGray(n)),t=t.replace(/\*\*([^*]+)\*\*/g,(r,n)=>ft.bold(n)),t=t.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(r,n)=>ft.italic(n)),t=t.replace(/(?<!_)_([^_]+)_(?!_)/g,(r,n)=>ft.italic(n)),t=t.replace(/~([^~]+)~/g,(r,n)=>ft.strikethrough(n)),t}supportsHyperlinks(){if(ur())return!1;let e=bt.env;if(!e)return!1;if(e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"||e.TERM_PROGRAM==="WezTerm")return!0;if(e.WT_SESSION)return!0;if(e.TERM==="xterm-kitty")return!0;let t=e.VTE_VERSION?Number.parseInt(e.VTE_VERSION,10):0;if(!Number.isNaN(t)&&t>=5000)return!0;return!1}toAbsoluteFilePath(e){try{let t=e;if(t.startsWith("file://"))t=t.replace(/^file:\/\//,"");if(t.startsWith("~")){let r=bt.env.HOME||"";if(r)t=t.replace(/^~(?=$|\/)/,r)}if(tw(t)||t.startsWith("./")||t.startsWith("../"))t=rw(t);else return null;return Sc(t)?t:null}catch{return null}}buildOutputTexts(e){let t=this.shouldStyleConsole()?this.formatMarkdown(e):e,r=e.replace(this.ANSI_PATTERN,"");return{consoleText:t,fileText:r}}async log(e,t,...r){let n=new Date,i=this.formatConsoleTimestamp(n),o=this.formatFileTimestamp(n),s,c;if(t instanceof Error)s=t.message,c=t.stack;else s=this.formatMessage(t,r);let{consoleText:l,fileText:a}=this.buildOutputTexts(s);if(this.shouldStyleConsole()){let E=this.options.showIcons===!1?"":pf[e],k=this.options.showTags!==!1&&this.name?ft.gray(this.formatTag(this.name)):"",O;switch(e){case"debug":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:ft.gray(l),level:e}),console.error(O);break;case"info":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.warn(O);break;case"success":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:ft.green(l),level:e}),console.error(O);break;case"warning":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.warn(O);break;case"error":if(O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.error(O),c){let q=c.split(`
|
|
69
|
+
`);for(let G of q)if(G.trim()&&!G.includes(s))console.error(this.formatConsoleMessage({timestamp:i,message:ft.gray(` ${G}`),level:e,showTimestamp:!1}))}break}}else if(!ur()){if(console.error(`${o} ${this.environment}.${e.toUpperCase()}: ${s}`),c)console.error(c)}if(!this.shouldLog(e))return;let m=`${o} ${this.environment}.${e.toUpperCase()}: ${a}
|
|
70
|
+
`;if(c)m+=`${c}
|
|
71
|
+
`;if(m=m.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(m)}progress(e,t=""){let r={update:(c,l)=>{},finish:(c)=>{},interrupt:(c,l)=>{}};if(!this.enabled)return r;let n=30;if(this.activeProgressBar={total:Math.max(1,e||1),current:0,message:t||"",barLength:n,lastRenderedLine:""},this.shouldStyleConsole()&&!ur()&&bt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar);return{update:(c,l)=>{if(!this.enabled||!this.activeProgressBar)return;if(this.activeProgressBar.current=Math.min(Math.max(0,c),this.activeProgressBar.total),l!==void 0)this.activeProgressBar.message=l;if(this.shouldStyleConsole()&&!ur()&&bt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)},finish:(c)=>{if(!this.activeProgressBar)return;this.finishProgressBar(this.activeProgressBar,c)},interrupt:(c,l="info")=>{if(!ur()&&bt.stdout.isTTY)bt.stdout.write(`
|
|
72
|
+
`);if(this[l==="warning"?"warn":l](c),this.activeProgressBar&&this.shouldStyleConsole()&&!ur()&&bt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)}}}time(e){let t=performance.now();if(this.shouldStyleConsole()){let r=this.options.showTags!==!1&&this.name?ft.gray(this.formatTag(this.name)):"",n=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:n,icon:this.options.showIcons===!1?"":ft.blue("◐"),tag:r,message:`${ft.cyan(e)}...`}))}return async(r)=>{if(!this.enabled)return;let n=performance.now(),i=Math.round(n-t),o=`${e} completed in ${i}ms`,s=new Date,c=this.formatConsoleTimestamp(s),a=`${this.formatFileTimestamp(s)} ${this.environment}.INFO: ${o}`;if(r)a+=` ${JSON.stringify(r)}`;if(a+=`
|
|
73
|
+
`,a=a.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let m=this.options.showTags!==!1&&this.name?ft.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:c,icon:this.options.showIcons===!1?"":ft.green("✓"),tag:m,message:`${o}${r?` ${JSON.stringify(r)}`:""}`}))}else if(!ur())console.error(a.trim());if(this.shouldWriteToFile())await this.writeToFile(a)}}async debug(e,...t){await this.log("debug",e,...t)}async info(e,...t){await this.log("info",e,...t)}async success(e,...t){await this.log("success",e,...t)}async warn(e,...t){await this.log("warning",e,...t)}async error(e,...t){await this.log("error",e,...t)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let e=this.config.rotation,{encrypt:t}=e;return!!t}async only(e){if(!this.enabled)return;return await e()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e}extend(e){let t=`${this.name}:${e}`,r=new Vc(t,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(r),r}createReadStream(){if(ur())throw Error("createReadStream is not supported in browser environments");if(!Sc(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return Sm(this.currentLogFile,{encoding:"utf8"})}async decrypt(e){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let t=this.config.rotation;if(!t.encrypt||typeof t.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let r=this.keys.get(this.currentKeyId);try{let n=Qi.isBuffer(e)?e:Qi.from(e,"base64"),i=n.subarray(0,16),o=n.subarray(n.length-16),s=n.subarray(16,n.length-16),c=Qv("aes-256-gcm",r,i);c.setAuthTag(o);let l=c.update(s),a=c.final(),m=l.length+a.length,E=Qi.allocUnsafe(m);return l.copy(E,0),a.copy(E,l.length),E.toString("utf8")}catch(n){throw Error(`Decryption failed: ${n instanceof Error?n.message:String(n)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return ur()}isServerMode(){return!ur()}setTestEncryptionKey(e,t){this.currentKeyId=e,this.keys.set(e,t)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box(e){if(!this.enabled)return;let t=new Date,r=this.formatConsoleTimestamp(t),n=this.formatFileTimestamp(t),{consoleText:i,fileText:o}=this.buildOutputTexts(e);if(this.shouldStyleConsole()){let c=i.split(`
|
|
74
|
+
`),l=Math.max(...c.map((k)=>k.length))+2,a=`┌${"─".repeat(l)}┐`,m=`└${"─".repeat(l)}┘`,E=c.map((k)=>this.formatConsoleMessage({timestamp:r,message:ft.cyan(k),showTimestamp:!1}));console.error(this.formatConsoleMessage({timestamp:r,message:ft.cyan(a),showTimestamp:!1})),E.forEach((k)=>console.error(k)),console.error(this.formatConsoleMessage({timestamp:r,message:ft.cyan(m),showTimestamp:!1}))}else if(!ur())console.error(`${n} ${this.environment}.INFO: [BOX] ${o}`);let s=`${n} ${this.environment}.INFO: [BOX] ${o}
|
|
75
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(s)}async prompt(e){if(ur())return Promise.resolve(!0);return new Promise((t)=>{console.error(`${ft.cyan("?")} ${e} (y/n) `);let r=(n)=>{let i=n.toString().trim().toLowerCase();bt.stdin.removeListener("data",r);try{if(typeof bt.stdin.setRawMode==="function")bt.stdin.setRawMode(!1)}catch{}bt.stdin.pause(),console.error(""),t(i==="y"||i==="yes")};try{if(typeof bt.stdin.setRawMode==="function")bt.stdin.setRawMode(!0)}catch{}bt.stdin.resume(),bt.stdin.once("data",r)})}setFancy(e){this.fancy=e}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start(e,...t){if(!this.enabled)return;let r=e;if(t&&t.length>0){let l=/%([sdijfo%])/g,a=0;if(r=e.replace(l,(m,E)=>{if(E==="%")return"%";if(a>=t.length)return m;let k=t[a++];switch(E){case"s":return String(k);case"d":case"i":return Number(k).toString();case"j":case"o":return JSON.stringify(k,null,2);default:return m}}),a<t.length)r+=` ${t.slice(a).map((m)=>typeof m==="object"?JSON.stringify(m,null,2):String(m)).join(" ")}`}let{consoleText:n,fileText:i}=this.buildOutputTexts(r);if(this.shouldStyleConsole()){let l=this.options.showTags!==!1&&this.name?ft.gray(this.formatTag(this.name)):"",a=this.options.showIcons===!1?"":`${ft.blue("◐")} `;console.error(`${a}${l} ${ft.cyan(n)}`)}let c=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${i}
|
|
76
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(c)}renderProgressBar(e,t=!1){if(!this.enabled||!this.shouldStyleConsole()||!bt.stdout.isTTY)return;let r=Math.min(100,Math.max(0,Math.round(e.current/e.total*100))),n=Math.round(e.barLength*r/100),i=e.barLength-n,o=ft.green("━".repeat(n)),s=ft.gray("━".repeat(i)),c=`[${o}${s}]`,l=`${r}%`.padStart(4),a=e.message?` ${e.message}`:"",m=this.options.showIcons===!1?"":t||r===100?ft.green("✓"):ft.blue("▶"),E=this.options.showTags!==!1&&this.name?` ${ft.gray(this.formatTag(this.name))}`:"",k=`\r${m}${E} ${c} ${l}${a}`,O=bt.stdout.columns||80,q=" ".repeat(Math.max(0,O-k.replace(this.ANSI_PATTERN,"").length));if(e.lastRenderedLine=`${k}${q}`,bt.stdout.write(e.lastRenderedLine),t)bt.stdout.write(`
|
|
77
|
+
`)}finishProgressBar(e,t){if(!this.enabled||!this.fancy||ur()||!bt.stdout.isTTY){this.activeProgressBar=null;return}if(e.current<e.total)e.current=e.total;if(t)e.message=t;this.renderProgressBar(e,!0),this.activeProgressBar=null}async clear(e={}){if(ur()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let t=await vc(this.config.logDirectory),r=[];for(let n of t){if(!(e.name?new RegExp(e.name.replace("*",".*")).test(n):n.startsWith(this.name))||!n.endsWith(".log"))continue;let o=zs(this.config.logDirectory,n);if(e.before)try{if((await Us(o)).mtime>=e.before)continue}catch(s){console.error(`Failed to get stats for file ${o}:`,s);continue}r.push(o)}if(r.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${r.length} log file(s)...`);for(let n of r)try{await wc(n),console.warn(`Deleted log file: ${n}`)}catch(i){console.error(`Failed to delete log file ${n}:`,i)}console.warn("Log clearing process finished.")}catch(t){console.error("Error during log clearing process:",t)}}}async function rf(e,t={}){let{maxRetries:r=3,retryDelay:n=1000,isRetryable:i=()=>!0,fallback:o}=t,s=Error("Unknown error occurred");for(let c=0;c<=r;c++)try{return await e()}catch(l){if(s=l instanceof Error?l:Error(String(l)),c===r||!i(s))break;if(n>0)await new Promise((a)=>setTimeout(a,n))}if(o!==void 0)return o;throw s instanceof Error?s:Error(`Unknown error: ${String(s)}`)}function nf(e){return e instanceof ri}function Lw(e){return e instanceof qc}function Bw(e){if(nf(e))return e.code==="FILE_SYSTEM_ERROR"||e.code==="BROWSER_CONFIG_ERROR";return["ENOENT","EACCES","EMFILE","ENFILE","EBUSY","network","timeout","connection"].some((r)=>e.message.toLowerCase().includes(r.toLowerCase()))}class Qc{defaultParsers;constructor(){this.defaultParsers=[{name:"boolean",canParse:(e,t)=>t==="boolean"||["true","false","1","0","yes","no"].includes(e.toLowerCase()),parse:(e)=>{let t=e.toLowerCase();return["true","1","yes"].includes(t)}},{name:"number",canParse:(e,t)=>t==="number"||!Number.isNaN(Number(e))&&!Number.isNaN(Number.parseFloat(e)),parse:(e)=>{let t=Number(e);if(Number.isNaN(t))throw TypeError(`Cannot parse "${e}" as number`);return t}},{name:"array",canParse:(e,t)=>t==="array"||e.startsWith("[")||e.includes(","),parse:(e)=>{try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return e.split(",").map((t)=>t.trim())}},{name:"json",canParse:(e,t)=>t==="object"||(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]")),parse:(e)=>{try{return JSON.parse(e)}catch(t){throw Error(`Cannot parse "${e}" as JSON: ${t}`)}}}]}async applyEnvironmentVariables(e,t,r={}){let{prefix:n,useCamelCase:i=!0,useBackwardCompatibility:o=!0,customParsers:s={},verbose:c=!1,trackPerformance:l=!0}=r,a=async()=>{if(!e)return{config:t,source:{type:"environment",priority:50,timestamp:new Date}};let m=n||this.generateEnvPrefix(e),E={...t};return this.processObject(E,[],m,{useCamelCase:i,useBackwardCompatibility:o,customParsers:s,verbose:c,configName:e}),{config:E,source:{type:"environment",priority:50,timestamp:new Date}}};if(l)return Pa.track("applyEnvironmentVariables",a,{configName:e});return a()}generateEnvPrefix(e){return e.toUpperCase().replace(/-/g,"_")}formatEnvKey(e,t){if(!t)return e.toUpperCase();return e.replace(/([A-Z])/g,"_$1").toUpperCase()}processObject(e,t,r,n){for(let[i,o]of Object.entries(e)){let s=[...t,i],c=s.map((m)=>this.formatEnvKey(m,n.useCamelCase)),l=`${r}_${c.join("_")}`,a=n.useBackwardCompatibility?`${r}_${s.map((m)=>m.toUpperCase()).join("_")}`:null;if(n.verbose);if(typeof o==="object"&&o!==null&&!Array.isArray(o))this.processObject(o,s,r,n);else{let m=Ic.env[l]||(a?Ic.env[a]:void 0);if(m!==void 0){if(n.verbose){let E=Ic.env[l]?l:a}try{e[i]=this.parseEnvironmentValue(m,typeof o,l,n.customParsers,n.configName)}catch(E){if(E instanceof Jc)throw E;throw Po.envVar(l,m,typeof o,n.configName)}}}}}parseEnvironmentValue(e,t,r,n,i){for(let[o,s]of Object.entries(n))try{return s(e)}catch{continue}for(let o of this.defaultParsers)if(o.canParse(e,t))try{return o.parse(e)}catch{throw Po.envVar(r,e,`${t} (via ${o.name} parser)`,i)}return e}getEnvironmentVariables(e){let t={},r=e.toUpperCase();for(let[n,i]of Object.entries(Ic.env))if(n.startsWith(r)&&i!==void 0)t[n]=i;return t}validateEnvironmentVariable(e,t,r){let n=[];if(!/^[A-Z_][A-Z0-9_]*$/.test(e))n.push(`Environment variable key "${e}" should only contain uppercase letters, numbers, and underscores`);if(r)try{this.parseEnvironmentValue(e,t,r,{})}catch(i){n.push(`Cannot parse value "${t}" as ${r}: ${i}`)}return{isValid:n.length===0,errors:n}}generateEnvVarDocs(e,t,r={}){let{prefix:n,format:i="text"}=r,o=n||this.generateEnvPrefix(e),s=[];switch(this.extractEnvVarInfo(t,[],o,s),i){case"markdown":return this.formatAsMarkdown(s,e);case"json":return JSON.stringify(s,null,2);default:return this.formatAsText(s,e)}}extractEnvVarInfo(e,t,r,n){for(let[i,o]of Object.entries(e)){let s=[...t,i],c=`${r}_${s.map((l)=>this.formatEnvKey(l,!0)).join("_")}`;if(typeof o==="object"&&o!==null&&!Array.isArray(o))this.extractEnvVarInfo(o,s,r,n);else n.push({key:c,type:Array.isArray(o)?"array":typeof o,description:`Configuration for ${s.join(".")}`,example:this.generateExample(o)})}}generateExample(e){if(Array.isArray(e))return JSON.stringify(e);if(typeof e==="object"&&e!==null)return JSON.stringify(e);return String(e)}formatAsText(e,t){let r=`Environment Variables for ${t}:
|
|
78
|
+
|
|
79
|
+
`;for(let n of e)r+=`${n.key}
|
|
80
|
+
`,r+=` Type: ${n.type}
|
|
81
|
+
`,r+=` Description: ${n.description}
|
|
82
|
+
`,r+=` Example: ${n.example}
|
|
83
|
+
|
|
84
|
+
`;return r}formatAsMarkdown(e,t){let r=`# Environment Variables for ${t}
|
|
85
|
+
|
|
86
|
+
`;r+=`| Variable | Type | Description | Example |
|
|
87
|
+
`,r+=`|----------|------|-------------|----------|
|
|
88
|
+
`;for(let n of e)r+=`| \`${n.key}\` | ${n.type} | ${n.description} | \`${n.example}\` |
|
|
89
|
+
`;return r}}function jw(e,t){let r=df("process");if(typeof r>"u"||!r.env)return t;let n=r.env[e];return n!==void 0?n:t}function of(e,t,r={}){return sf(e,t,r,new WeakMap)}function sf(e,t,r,n){let{arrayMergeMode:i="replace",skipNullish:o=!1,customMerger:s}=r;if(t===null||t===void 0)return o?e:t;if(s){let c=s(e,t);if(c!==void 0)return c}if(Array.isArray(t)||Array.isArray(e))return af(e,t,i,n);if(!ci(t)||!ci(e))return t;return Vw(e,t,r,n)}function af(e,t,r,n){if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(e)&&!Array.isArray(t))return t;if(Array.isArray(t)&&Array.isArray(e))switch(r){case"replace":return t;case"concat":return Fw(e,t);case"smart":return Uw(e,t,n);default:return t}return t}function Fw(e,t){let r=[...t];for(let n of e)if(!r.some((i)=>Wu(i,n)))r.push(n);return r}function Uw(e,t,r){if(t.length===0)return e;if(e.length===0)return t;if(ci(t[0])&&ci(e[0]))return zw(e,t,r);if(t.every((n)=>typeof n==="string")&&e.every((n)=>typeof n==="string")){let n=[...t];for(let i of e)if(!n.includes(i))n.push(i);return n}return t}function zw(e,t,r){let n=[...t];for(let i of e){if(!ci(i)){n.push(i);continue}let o=["id","name","key","path","type"],s=!1;for(let c of o)if(c in i){if(n.find((a)=>ci(a)&&(c in a)&&a[c]===i[c])){s=!0;break}}if(!s)n.push(i)}return n}function Vw(e,t,r,n){let i=t;if(ci(i)&&n.has(i))return n.get(i);let o={...e};if(ci(i))n.set(i,o);for(let s in i){if(!Object.prototype.hasOwnProperty.call(i,s))continue;let c=i[s],l=o[s];if(r.skipNullish&&(c===null||c===void 0))continue;if(c===null||c===void 0){o[s]=c;continue}if(ci(c)&&ci(l))o[s]=sf(l,c,r,n);else if(Array.isArray(c)||Array.isArray(l))o[s]=af(l,c,r.arrayMergeMode||"smart",n);else o[s]=c}return o}function al(e,t,r="replace"){return of(e,t,{arrayMergeMode:r==="replace"?"replace":"smart",skipNullish:!0})}function Wu(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!Wu(e[r],t[r]))return!1;return!0}if(ci(e)&&ci(t)){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let i of r){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!Wu(e[i],t[i]))return!1}return!0}return!1}function ci(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}class Yc{extensions=[".ts",".js",".mjs",".cjs",".json",".mts",".cts"];async loadFromPath(e,t,r={}){let{arrayStrategy:n="replace",useCache:i=!0,cacheTtl:o,trackPerformance:s=!0,verbose:c=!1}=r;if(i){let a=Hs.getWithFileCheck("file",e);if(a){if(c)console.log(`Configuration loaded from cache: ${e}`);return a}}let l=async()=>{if(!Cc(e))return null;try{let a=`?t=${Date.now()}`,m=await import(e+a),E=m.default||m,k="default"in m,O=Object.keys(m).length>0;if(!k&&!O)throw new ka(e,Error("Configuration file is empty and exports nothing"),"unknown");if(typeof E!=="object"||E===null||Array.isArray(E))throw new ka(e,Error("Configuration must export a valid object"),"unknown");let Y={config:al(t,E,n),source:{type:"file",path:e,priority:100,timestamp:new Date}};if(i)Hs.setWithFileCheck("file",Y,e,o);return Y}catch(a){throw a instanceof Error?Po.configLoad(e,a):Po.configLoad(e,Error(String(a)))}};if(s)return Pa.track("loadFromPath",l,{path:e});return l()}async tryLoadFromPaths(e,t,r={}){for(let n of e)try{let i=await this.loadFromPath(n,t,r);if(i)return i}catch(i){if(i instanceof Error&&i.name==="ConfigLoadError")throw i;if(r.verbose)console.warn(`Failed to load config from ${n}:`,i)}return null}generateConfigPaths(e,t,r){let n=this.generateNamePatterns(e,r),i=[];for(let o of n)for(let s of this.extensions)i.push(_u(t,`${o}${s}`));return i}generateNamePatterns(e,t){let r=[];if(r.push("config",".config"),e)r.push(e,`.${e}.config`,`${e}.config`,`.${e}`);if(t){if(r.push(t,`.${t}.config`,`${t}.config`,`.${t}`),e)r.push(`${e}.${t}.config`,`.${e}.${t}.config`)}return r.filter(Boolean)}checkFileAccess(e){return rf(async()=>Cc(e),{maxRetries:2,retryDelay:100,fallback:!1})}async discoverConfigFiles(e,t,r){let n=[];if(!Cc(e))return n;if(t||r){let i=this.generateNamePatterns(t||"",r);for(let o of i)for(let s of this.extensions){let c=_u(e,`${o}${s}`);if(await this.checkFileAccess(c))n.push(c)}}else try{let{readdirSync:i}=await import("fs"),o=i(e);for(let s of o)if(this.looksLikeConfigFile(s)){let c=_u(e,s);if(await this.checkFileAccess(c))n.push(c)}}catch{return[]}return n}looksLikeConfigFile(e){return[/\.config\.(ts|js|mjs|cjs|json|mts|cts)$/,/^\..*\.(ts|js|mjs|cjs|json|mts|cts)$/,/config\.(ts|js|mjs|cjs|json|mts|cts)$/].some((r)=>r.test(e))}async validateConfigFile(e){let t=[];try{if(!Cc(e))return t.push("Configuration file does not exist"),t;let r=await import(e),n=r.default||r;if(n===void 0)t.push("Configuration file must export a default value or named exports");else if(typeof n!=="object"||n===null)t.push("Configuration must be an object");else if(Array.isArray(n))t.push("Configuration cannot be an array at the root level");if(e.endsWith(".json"))try{let{readFileSync:i}=await import("fs"),o=i(e,"utf8");JSON.parse(o)}catch(i){t.push(`Invalid JSON syntax: ${i}`)}}catch(r){t.push(`Failed to load configuration file: ${r}`)}return t}async getFileModificationTime(e){try{let{statSync:t}=await import("fs");return t(e).mtime}catch{return null}}async preloadConfigurations(e,t={}){let r=new Map;return await Promise.allSettled(e.map(async(n)=>{try{let i=await this.loadFromPath(n,{},t);if(i)r.set(n,i.config)}catch(i){if(t.verbose)console.warn(`Failed to preload ${n}:`,i)}})),r}}class cl{async validateConfiguration(e,t,r={}){let{stopOnFirstError:n=!1,validateRequired:i=!0,validateTypes:o=!0,customRules:s=[],trackPerformance:c=!0,verbose:l=!1}=r,a=async()=>{let m=[],E=[],k={stopOnFirstError:n,validateRequired:i,validateTypes:o,customRules:s,trackPerformance:c,verbose:l};try{if(typeof t==="string")return await this.validateWithSchemaFile(e,t,k);else if(Array.isArray(t))return this.validateWithRules(e,[...t,...s],k);else return this.validateWithJSONSchema(e,t,k)}catch(O){return m.push({path:"",message:`Validation failed: ${O}`,rule:"system"}),{isValid:!1,errors:m,warnings:E}}};if(c)return await Pa.track("validateConfiguration",a);return a()}async validateWithSchemaFile(e,t,r){try{if(!iw(t))throw new Ra(t,[{path:"",message:"Schema file does not exist"}]);let n=await import(t),i=n.default||n;if(Array.isArray(i))return this.validateWithRules(e,i,r);else return this.validateWithJSONSchema(e,i,r)}catch(n){throw new Ra(t,[{path:"",message:`Failed to load schema: ${n}`}])}}validateWithJSONSchema(e,t,r){let n=[],i=[];return this.validateObjectAgainstSchema(e,t,"",n,i,r),{isValid:n.length===0,errors:n,warnings:i}}validateObjectAgainstSchema(e,t,r,n,i,o){if(o.validateTypes&&t.type){let s=Array.isArray(e)?"array":typeof e,c=Array.isArray(t.type)?t.type:[t.type];if(!c.includes(s)){if(n.push({path:r,message:`Expected type ${c.join(" or ")}, got ${s}`,expected:c.join(" or "),actual:s,rule:"type"}),o.stopOnFirstError)return}}if(t.enum&&!t.enum.includes(e)){if(n.push({path:r,message:`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"}),o.stopOnFirstError)return}if(typeof e==="string"){if(t.minLength!==void 0&&e.length<t.minLength)n.push({path:r,message:`String length must be at least ${t.minLength}`,expected:`>= ${t.minLength}`,actual:e.length,rule:"minLength"});if(t.maxLength!==void 0&&e.length>t.maxLength)n.push({path:r,message:`String length must not exceed ${t.maxLength}`,expected:`<= ${t.maxLength}`,actual:e.length,rule:"maxLength"});if(t.pattern){if(!new RegExp(t.pattern).test(e))n.push({path:r,message:`String does not match pattern ${t.pattern}`,expected:t.pattern,actual:e,rule:"pattern"})}}if(typeof e==="number"){if(t.minimum!==void 0&&e<t.minimum)n.push({path:r,message:`Value must be at least ${t.minimum}`,expected:`>= ${t.minimum}`,actual:e,rule:"minimum"});if(t.maximum!==void 0&&e>t.maximum)n.push({path:r,message:`Value must not exceed ${t.maximum}`,expected:`<= ${t.maximum}`,actual:e,rule:"maximum"})}if(Array.isArray(e)&&t.items)for(let s=0;s<e.length;s++){let c=r?`${r}[${s}]`:`[${s}]`;if(this.validateObjectAgainstSchema(e[s],t.items,c,n,i,o),o.stopOnFirstError&&n.length>0)return}if(e&&typeof e==="object"&&!Array.isArray(e)){let s=e;if(o.validateRequired&&t.required){for(let c of t.required)if(!(c in s)){if(n.push({path:r?`${r}.${c}`:c,message:`Missing required property '${c}'`,expected:"required",rule:"required"}),o.stopOnFirstError)return}}if(t.properties){for(let[c,l]of Object.entries(t.properties))if(c in s){let a=r?`${r}.${c}`:c;if(this.validateObjectAgainstSchema(s[c],l,a,n,i,o),o.stopOnFirstError&&n.length>0)return}}if(t.additionalProperties===!1){let c=new Set(Object.keys(t.properties||{}));for(let l of Object.keys(s))if(!c.has(l))i.push({path:r?`${r}.${l}`:l,message:`Additional property '${l}' is not allowed`,rule:"additionalProperties"})}}}validateWithRules(e,t,r){let n=[],i=[];for(let o of t)try{let s=this.getValueByPath(e,o.path),c=this.validateWithRule(s,o,o.path);if(n.push(...c),r.stopOnFirstError&&n.length>0)break}catch(s){n.push({path:o.path,message:`Rule validation failed: ${s}`,rule:"system"})}return{isValid:n.length===0,errors:n,warnings:i}}validateWithRule(e,t,r){let n=[];if(t.required&&(e===void 0||e===null))return n.push({path:r,message:t.message||`Property '${r}' is required`,expected:"required",rule:"required"}),n;if(e===void 0||e===null)return n;if(t.type){let i=Array.isArray(e)?"array":typeof e;if(i!==t.type)n.push({path:r,message:t.message||`Expected type ${t.type}, got ${i}`,expected:t.type,actual:i,rule:"type"})}if(t.min!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i<t.min)n.push({path:r,message:t.message||`Value must be at least ${t.min}`,expected:`>= ${t.min}`,actual:i,rule:"min"})}if(t.max!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i>t.max)n.push({path:r,message:t.message||`Value must not exceed ${t.max}`,expected:`<= ${t.max}`,actual:i,rule:"max"})}if(t.pattern&&typeof e==="string"){if(!t.pattern.test(e))n.push({path:r,message:t.message||`Value does not match pattern ${t.pattern}`,expected:t.pattern.toString(),actual:e,rule:"pattern"})}if(t.enum&&!t.enum.includes(e))n.push({path:r,message:t.message||`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"});if(t.validator){let i=t.validator(e);if(i)n.push({path:r,message:t.message||i,rule:"custom"})}return n}getValueByPath(e,t){if(!t)return e;let r=t.split("."),n=e;for(let i of r)if(n&&typeof n==="object"&&i in n)n=n[i];else return;return n}generateRulesFromInterface(e){let t=[],r=e.matchAll(/(\w+)(\?)?:\s*(\w+)/g);for(let n of r){let[,i,o,s]=n;t.push({path:i,required:!o,type:this.mapTypeScriptType(s)})}return t}mapTypeScriptType(e){switch(e.toLowerCase()){case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"array":return"array";case"object":return"object";default:return"object"}}static createCommonRules(){return{server:[{path:"port",required:!0,type:"number",min:1,max:65535},{path:"host",required:!0,type:"string",min:1},{path:"ssl",type:"boolean"}],database:[{path:"url",required:!0,type:"string",min:1},{path:"pool",type:"number",min:1,max:100},{path:"timeout",type:"number",min:0}],api:[{path:"baseUrl",required:!0,type:"string",pattern:mf},{path:"timeout",type:"number",min:0},{path:"retries",type:"number",min:0,max:10}]}}}class dl{fileLoader=new Yc;envProcessor=new Qc;validator=new cl;async loadConfig(e){let t=Date.now(),{cache:r,performance:n,schema:i,validate:o,...s}=e;try{if(r?.enabled){let l=this.checkCache(s.name||"",s);if(l)return l}let c;try{c=await this.loadConfigurationStrategies(s,!0,r)}catch(l){let a=s.__strictErrorHandling;if(l instanceof Error&&l.name==="ConfigNotFoundError"){if(a)throw l;c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`No configuration file found for "${s.name||"config"}", using defaults with environment variables`]}}else if(l instanceof Error&&l.name==="ConfigLoadError"){let m=l.message.includes("EACCES")||l.message.includes("EPERM")||l.message.includes("permission denied"),E=!m&&(l.message.includes("syntax")||l.message.includes("Expected")||l.message.includes("Unexpected")||l.message.includes("BuildMessage")||l.message.includes("errors building")),k=l.message.includes("Configuration must export a valid object")||l.message.includes("Configuration file is empty and exports nothing");if(a&&(k||m))throw l;if(E&&(!a||!k))c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:["Configuration file has syntax errors, using defaults with environment variables"]};else if(!a)c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`Configuration loading error, using defaults: ${l.message}`]};else throw l}else c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`Configuration loading failed, using defaults: ${l instanceof Error?l.message:String(l)}`]}}if(i||o)await this.validateConfiguration(c.config,i,o,s.name);if(r?.enabled&&c)this.cacheResult(s.name||"",c,r,s);if(n?.enabled){let l={operation:"loadConfig",duration:Date.now()-t,configName:s.name,timestamp:new Date};if(n.onMetrics)n.onMetrics(l);if(n.slowThreshold&&l.duration>n.slowThreshold)hi.warn(`Slow configuration loading detected: ${l.duration}ms for ${s.name}`);c.metrics=l}return c}catch(c){let l=Date.now()-t;throw hi.error(`Configuration loading failed after ${l}ms:`,[c instanceof Error?c:Error(String(c))]),c}}async loadConfigurationStrategies(e,t=!1,r){let{name:n="",alias:i,cwd:o,configDir:s,defaultConfig:c,checkEnv:l=!0,arrayStrategy:a="replace",verbose:m=!1}=e,E=o||as.cwd(),k=[],O=await this.loadLocalConfiguration(n,i,E,s,c,a,m,l,r);if(O)return k.push(...this.getLocalSearchPaths(n,i,E,s)),this.finalizeResult(O,k,l,n,m);let q=await this.loadHomeConfiguration(n,i,c,a,m,l);if(q)return k.push(...this.getHomeSearchPaths(n,i)),this.finalizeResult(q,k,l,n,m);let G=await this.loadPackageJsonConfiguration(n,i,E,c,a,m,l);if(G)return k.push(Bn(E,"package.json")),this.finalizeResult(G,k,l,n,m);if(k.push(...this.getAllSearchPaths(n,i,E,s)),t)throw Po.configNotFound(n,k,i);return{...await this.applyEnvironmentVariables(n,c,l,m),warnings:[`No configuration file found for "${n}"${i?` or alias "${i}"`:""}, using defaults with environment variables`]}}async loadLocalConfiguration(e,t,r,n,i,o,s,c,l){let a=c?Ta(e,i,s):i,m=this.getLocalDirectories(r,n);for(let E of m){if(s)hi.info(`Searching for configuration in: ${E}`);let k=this.fileLoader.generateConfigPaths(e,E,t),O=await this.fileLoader.tryLoadFromPaths(k,a,{arrayStrategy:o,verbose:s,cacheTtl:l?.ttl,useCache:!l?.ttl||l.ttl>100});if(O){if(s)hi.success(`Configuration loaded from: ${O.source.path}`);return O}}return null}async loadHomeConfiguration(e,t,r,n,i,o){if(!e)return null;let s=o?Ta(e,r,i):r,c=[Bn(Ls(),".config",e),Bn(Ls(),".config"),Ls()];for(let l of c){if(i)hi.info(`Checking home directory: ${l}`);let a=this.fileLoader.generateConfigPaths(e,l,t),m=await this.fileLoader.tryLoadFromPaths(a,s,{arrayStrategy:n,verbose:i});if(m){if(i)hi.success(`Configuration loaded from home directory: ${m.source.path}`);return m}}return null}async loadPackageJsonConfiguration(e,t,r,n,i,o,s){let c=s?Ta(e,n,o):n;try{let l=Bn(r,"package.json");if(!qu(l))return null;let a=await import(l),m=a[e],E=e;if(!m&&t)m=a[t],E=t;if(m&&typeof m==="object"&&!Array.isArray(m)){if(o)hi.success(`Configuration loaded from package.json: ${E}`);return{config:al(c,m,i),source:{type:"package.json",path:l,priority:30,timestamp:new Date}}}}catch(l){if(o)hi.warn("Failed to load package.json:",[l instanceof Error?l:Error(String(l))])}return null}async applyEnvironmentVariables(e,t,r,n){if(!r||!e||typeof t!=="object"||t===null||Array.isArray(t))return{config:t,source:{type:"default",priority:10,timestamp:new Date}};return{config:Ta(e,t,n),source:{type:"environment",priority:20,timestamp:new Date}}}async finalizeResult(e,t,r,n,i){return{config:e.config,source:e.source,path:e.source.path}}async validateConfiguration(e,t,r,n){let i=[];if(r){let o=r(e);if(o)i.push(...o)}if(t){let o=await this.validator.validateConfiguration(e,t);if(!o.isValid)i.push(...o.errors.map((s)=>s.path?`${s.path}: ${s.message}`:s.message))}if(i.length>0)throw Po.configValidation(n||"unknown",i,n)}checkCache(e,t){let r=this.generateCacheKey(e,t);return Hs.get(r)||null}cacheResult(e,t,r,n){let i=this.generateCacheKey(e,n);Hs.set(i,t,void 0,r.ttl)}generateCacheKey(e,t){let r=[e];if(t.alias)r.push(`alias:${t.alias}`);if(t.cwd)r.push(`cwd:${t.cwd}`);if(t.configDir)r.push(`configDir:${t.configDir}`);if("checkEnv"in t)r.push(`checkEnv:${t.checkEnv}`);return r.join("|")}getLocalDirectories(e,t){return Array.from(new Set([e,Bn(e,"config"),Bn(e,".config"),t?Bn(e,t):void 0].filter(Boolean)))}getAllSearchPaths(e,t,r,n){let i=[];return i.push(...this.getLocalSearchPaths(e,t,r,n)),i.push(...this.getHomeSearchPaths(e,t)),i.push(Bn(r,"package.json")),i}getLocalSearchPaths(e,t,r,n){let i=this.getLocalDirectories(r,n),o=[];for(let s of i)o.push(...this.fileLoader.generateConfigPaths(e,s,t));return o}getHomeSearchPaths(e,t){if(!e)return[];let r=[Bn(Ls(),".config",e),Bn(Ls(),".config"),Ls()],n=[];for(let i of r)n.push(...this.fileLoader.generateConfigPaths(e,i,t));return n}async loadConfigWithResult(e){return this.loadConfig(e)}}function _m(e){let r=!(e.message.includes("EACCES")||e.message.includes("EPERM")||e.message.includes("permission denied"))&&(e.message.includes("syntax")||e.message.includes("Expected")||e.message.includes("Unexpected")||e.message.includes("BuildMessage")),n=e.message.includes("Configuration must export a valid object")||e.message.includes("Configuration file is empty and exports nothing");return r||n}async function qw(e){return to.loadConfig({...e,__strictErrorHandling:!0})}async function cf(e){let t="defaultConfig"in e&&e.defaultConfig!==void 0?e.defaultConfig:{},r="cache"in e||"performance"in e||"schema"in e||"validate"in e;try{let n;if(r)n=await to.loadConfig(e);else n=await to.loadConfig({...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}});return n?.config??t}catch(n){let i=n instanceof Error?n.name:"UnknownError",o=n instanceof Error?n.message:String(n);if(!(i==="ConfigNotFoundError"||i==="ConfigLoadError"||i==="ConfigValidationError"||o.includes("config"))&&e.verbose)hi.warn("Unexpected error loading config, using defaults:",[n instanceof Error?n:Error(String(n))]);let c=r?{...e,defaultConfig:t}:{...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}};if("checkEnv"in e?e.checkEnv!==!1:!0)return(await to.applyEnvironmentVariables(c.name||"",t,!0,c.verbose||!1))?.config??t;return t}}async function Jw(e={defaultConfig:{}}){if(typeof e==="string"){let{cwd:t}=await import("process");try{return(await to.loadConfig({name:e,cwd:t(),generatedDir:"./generated",configDir:"./config",defaultConfig:{},checkEnv:!0,arrayStrategy:"replace"})).config}catch(r){if(r instanceof Error&&(r.name==="ConfigNotFoundError"||r.name==="ConfigLoadError"&&_m(r)))return(await to.applyEnvironmentVariables(e,{},!0,!1)).config;throw r}}try{return(await to.loadConfig({...e,cwd:e.cwd||as.cwd(),cache:{enabled:!0},performance:{enabled:!1}})).config}catch(t){if(t instanceof Error&&(t.name==="ConfigNotFoundError"||t.name==="ConfigLoadError"&&_m(t)))return(await to.applyEnvironmentVariables(e.name||"",e.defaultConfig||{},e.checkEnv!==!1,e.verbose||!1)).config;throw t}}async function Ww(e,t,r="replace"){let n=new Yc;try{let i=await n.loadFromPath(e,t,{arrayStrategy:r,useCache:!1,trackPerformance:!1});return i?i.config:null}catch{return null}}function Ta(e,t,r=!1){let n=new Qc,i=e.toUpperCase().replace(/[^A-Z0-9]/g,"_");function o(s,c=[]){let l={...s};for(let[a,m]of Object.entries(s)){let E=[...c,a],k=[`${i}_${E.join("_").toUpperCase()}`,`${i}_${E.map((G)=>G.toUpperCase()).join("")}`,`${i}_${E.map((G)=>G.replace(/([A-Z])/g,"_$1").toUpperCase()).join("")}`],O,q;for(let G of k)if(O=as.env[G],O!==void 0){q=G;break}if(O!==void 0&&q)if(typeof m==="boolean")l[a]=["true","1","yes"].includes(O.toLowerCase());else if(typeof m==="number"){let G=Number(O);if(!Number.isNaN(G))l[a]=G}else if(Array.isArray(m))try{l[a]=JSON.parse(O)}catch{l[a]=O.split(",").map((G)=>G.trim())}else l[a]=O;else if(m&&typeof m==="object"&&!Array.isArray(m))l[a]=o(m,E)}return l}return o(t)}function Hw(e){let t=Bn(as.cwd(),e.configDir),r=Bn(as.cwd(),e.generatedDir),n=Bn(r,"config-types.ts");if(!qu(um(n)))$v(um(n),{recursive:!0,mode:511});let i=qu(t)?Mv(t).map((s)=>s.replace(/\.(ts|js|mjs|cjs|mts|cts|json)$/,"")).sort():[],o=`// Generated by bunfig v${II}
|
|
90
|
+
export type ConfigNames = ${i.length?`'${i.join("' | '")}'`:"string"}
|
|
91
|
+
`;Lv(n,o,{mode:438})}function Gw(e){let t=null,r=null,n=()=>{if(!r)r=cf(e).then((o)=>(t=o,o),(o)=>{let s="defaultConfig"in e?e.defaultConfig:{};if(t=s,"verbose"in e&&e.verbose)hi.warn("Config loading failed, using defaults:",[o instanceof Error?o:Error(String(o))]);return s});return r},i="defaultConfig"in e?e.defaultConfig:{};return t=i,n(),new Proxy({},{get(o,s){if(t)return t[s];let c=i[s];return n(),c},has(o,s){return s in(t||i)},ownKeys(){return Object.keys(t||i)},getOwnPropertyDescriptor(o,s){return Object.getOwnPropertyDescriptor(t||i,s)},set(o,s,c){if(!t)t={...i};return t[s]=c,!0}})}function Kw(e){let t=Tm(aw.cwd(),e?.configDir||"./config");function r(){if(!ow(t))return[];let i=new Set([".ts",".js",".mjs",".cjs",".mts",".cts",".json"]),o=[".ts",".mts",".cts",".js",".mjs",".cjs",".json"],s=sw(t).filter((l)=>i.has(Nu(l))).map((l)=>({base:l.replace(/\.(?:ts|js|mjs|cjs|mts|cts|json)$/i,""),file:l})),c=new Map;for(let{base:l,file:a}of s){let m=Nu(a).toLowerCase(),E=c.get(l);if(!E){c.set(l,a);continue}let k=Nu(E).toLowerCase();if(o.indexOf(m)<o.indexOf(k))c.set(l,a)}return Array.from(c.entries()).map(([l,a])=>({base:l,file:a})).sort((l,a)=>l.base.localeCompare(a.base))}function n(){let i=r(),o=i.map((a)=>a.base),s=o.length?o.map((a)=>`'${a}'`).join(" | "):"string",c=i.length?`{
|
|
92
|
+
${i.map((a)=>{let m=Tm(t,a.file).replace(/\\/g,"/");return` '${a.base}': typeof import('${m}').default`}).join(`,
|
|
93
|
+
`)}
|
|
94
|
+
}`:"Record<string, any>";return`export type ConfigNames = ${s}
|
|
95
|
+
export type ConfigByName = ${c}
|
|
96
|
+
export type Config<N extends ConfigNames> = N extends keyof ConfigByName ? ConfigByName[N] : unknown
|
|
97
|
+
export type ConfigOf = Config
|
|
98
|
+
`}return{name:"bunfig-plugin",setup(i){i.onResolve({filter:/^virtual:bunfig-types$/},(o)=>({path:o.path,namespace:"bunfig-virtual"})),i.onLoad({filter:/^virtual:bunfig-types$/,namespace:"bunfig-virtual"},()=>({contents:n(),loader:"ts"}))}}}var df,Hs,Pa,uf,Qw,Yw,Nm,Dc,Hu,zr,xt,Xw,$m,Zw,Mm,eI,tI,Bu,rI,Lm,Bm,ju,nI,iI,oI,sI,Oc,lf,aI,Vr,cI,dI,jm,_c,Gu,lr,ft,uI,Fm,lI,Um,pI,gI,Fu,mI,zm,Vm,fI,Uu,hI,yI,bI,SI,vI,Nc,pf,wI,II="0.15.6",ri,qc,ka,Ku,Qu,Jc,Yu,Xu,Ra,Zu,el,Po,gf,mf,hi,to,ff,hf,CI=Cw(async()=>{df=import.meta.require,Hs=new nl,Pa=new il,uf={createKey:Ew,isEquivalent:Tw,estimateMemoryUsage:Aw},Qw=Bc(Ju.cwd(),"config"),Yw=Bc(Ju.cwd(),"src/generated"),Nm=Lc.env.CLARITY_LOG_DIR||Fv(Pw(),"logs"),Dc={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:Nm,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1},Hu=await xw(),zr={red:(e)=>`\x1B[31m${e}\x1B[0m`,green:(e)=>`\x1B[32m${e}\x1B[0m`,yellow:(e)=>`\x1B[33m${e}\x1B[0m`,blue:(e)=>`\x1B[34m${e}\x1B[0m`,magenta:(e)=>`\x1B[35m${e}\x1B[0m`,cyan:(e)=>`\x1B[36m${e}\x1B[0m`,white:(e)=>`\x1B[37m${e}\x1B[0m`,gray:(e)=>`\x1B[90m${e}\x1B[0m`,bgRed:(e)=>`\x1B[41m${e}\x1B[0m`,bgYellow:(e)=>`\x1B[43m${e}\x1B[0m`,bold:(e)=>`\x1B[1m${e}\x1B[0m`,dim:(e)=>`\x1B[2m${e}\x1B[0m`,italic:(e)=>`\x1B[3m${e}\x1B[0m`,underline:(e)=>`\x1B[4m${e}\x1B[0m`,reset:"\x1B[0m"},xt=zr,Xw=zr.red,$m=zr.green,Zw=zr.yellow,Mm=zr.blue,eI=zr.magenta,tI=zr.cyan,Bu=zr.white,rI=zr.gray,Lm=zr.bgRed,Bm=zr.bgYellow,ju=zr.bold,nI=zr.dim,iI=zr.italic,oI=zr.underline,sI=zr.reset,Oc={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},lf={debug:"\uD83D\uDD0D",info:Mm("ℹ"),success:$m("✓"),warning:Bm(Bu(ju(" WARN "))),error:Lm(Bu(ju(" ERROR ")))},aI=new Uc("stacks"),Vr=new Uc("bunfig",{showTags:!0}),cI=an(Aa.cwd(),"config"),dI=an(Aa.cwd(),"src/generated"),jm=Mc.env.CLARITY_LOG_DIR||Bv(Nw(),"logs"),_c={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:jm,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},Gu=await $w(),lr={red:(e)=>`\x1B[31m${e}\x1B[0m`,green:(e)=>`\x1B[32m${e}\x1B[0m`,yellow:(e)=>`\x1B[33m${e}\x1B[0m`,blue:(e)=>`\x1B[34m${e}\x1B[0m`,magenta:(e)=>`\x1B[35m${e}\x1B[0m`,cyan:(e)=>`\x1B[36m${e}\x1B[0m`,white:(e)=>`\x1B[37m${e}\x1B[0m`,gray:(e)=>`\x1B[90m${e}\x1B[0m`,bgRed:(e)=>`\x1B[41m${e}\x1B[0m`,bgYellow:(e)=>`\x1B[43m${e}\x1B[0m`,bgGray:(e)=>`\x1B[100m${e}\x1B[0m`,bold:(e)=>`\x1B[1m${e}\x1B[0m`,dim:(e)=>`\x1B[2m${e}\x1B[0m`,italic:(e)=>`\x1B[3m${e}\x1B[0m`,underline:(e)=>`\x1B[4m${e}\x1B[0m`,strikethrough:(e)=>`\x1B[9m${e}\x1B[0m`,reset:"\x1B[0m"},ft=lr,uI=lr.red,Fm=lr.green,lI=lr.yellow,Um=lr.blue,pI=lr.magenta,gI=lr.cyan,Fu=lr.white,mI=lr.gray,zm=lr.bgRed,Vm=lr.bgYellow,fI=lr.bgGray,Uu=lr.bold,hI=lr.dim,yI=lr.italic,bI=lr.underline,SI=lr.strikethrough,vI=lr.reset,Nc={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},pf={debug:"\uD83D\uDD0D",info:Um("ℹ"),success:Fm("✓"),warning:Vm(Fu(Uu(" WARN "))),error:zm(Fu(Uu(" ERROR ")))},wI=new Vc("stacks"),ri=class extends Error{timestamp;context;constructor(t,r={}){super(t);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=r,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let t=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([r,n])=>`${r}: ${n}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${t}`}},qc=class extends ri{code="CONFIG_NOT_FOUND";constructor(t,r,n){let i=n?` or alias "${n}"`:"";super(`Configuration "${t}"${i} not found`,{configName:t,alias:n,searchPaths:r,searchPathCount:r.length})}},ka=class extends ri{code="CONFIG_LOAD_ERROR";constructor(t,r,n){super(`Failed to load configuration from "${t}": ${r.message}`,{configPath:t,configName:n,originalError:r.name,originalMessage:r.message});this.cause=r}},Ku=class extends ri{code="CONFIG_VALIDATION_ERROR";constructor(t,r,n){super(`Configuration validation failed for "${t}"`,{configPath:t,configName:n,validationErrors:r,errorCount:r.length})}},Qu=class extends ri{code="CONFIG_MERGE_ERROR";constructor(t,r,n,i){super(`Failed to merge configuration from "${t}" with "${r}": ${n.message}`,{sourcePath:t,targetPath:r,configName:i,originalError:n.name,originalMessage:n.message});this.cause=n}},Jc=class extends ri{code="ENV_VAR_ERROR";constructor(t,r,n,i){super(`Failed to parse environment variable "${t}" with value "${r}" as ${n}`,{envKey:t,envValue:r,expectedType:n,configName:i})}},Yu=class extends ri{code="FILE_SYSTEM_ERROR";constructor(t,r,n){super(`File system ${t} failed for "${r}": ${n.message}`,{operation:t,path:r,originalError:n.name,originalMessage:n.message});this.cause=n}},Xu=class extends ri{code="TYPE_GENERATION_ERROR";constructor(t,r,n){super(`Failed to generate types from "${t}" to "${r}": ${n.message}`,{configDir:t,outputPath:r,originalError:n.name,originalMessage:n.message});this.cause=n}},Ra=class extends ri{code="SCHEMA_VALIDATION_ERROR";constructor(t,r,n){super(`Schema validation failed${n?` for config "${n}"`:""}`,{schemaPath:t,configName:n,validationErrors:r,errorCount:r.length})}},Zu=class extends ri{code="BROWSER_CONFIG_ERROR";constructor(t,r,n,i){super(`Failed to fetch configuration from "${t}": ${r} ${n}`,{endpoint:t,status:r,statusText:n,configName:i})}},el=class extends ri{code="PLUGIN_ERROR";constructor(t,r,n){super(`Plugin "${t}" failed during ${r}: ${n.message}`,{pluginName:t,operation:r,originalError:n.name,originalMessage:n.message});this.cause=n}},Po={configNotFound(e,t,r){return new qc(e,t,r)},configLoad(e,t,r){return new ka(e,t,r)},configValidation(e,t,r){return new Ku(e,t,r)},configMerge(e,t,r,n){return new Qu(e,t,r,n)},envVar(e,t,r,n){return new Jc(e,t,r,n)},fileSystem(e,t,r){return new Yu(e,t,r)},typeGeneration(e,t,r){return new Xu(e,t,r)},schemaValidation(e,t,r){return new Ra(e,t,r)},browserConfig(e,t,r,n){return new Zu(e,t,r,n)},plugin(e,t,r){return new el(e,t,r)}},gf={replace:"replace",concat:"concat",smart:"smart"},mf=/^https?:\/\//,hi=new Vc("bunfig",{showTags:!0}),to=new dl,ff=Bn(as.cwd(),"config"),hf=Bn(as.cwd(),"src/generated")});function EI(e,t={}){let r=jc.cwd();while(r.includes("storage"))r=Am(r,"..");let n=Am(r,e||"");if(t?.relative)return dw(jc.cwd(),n);return n}var TI=jc.env.CLARITY_LOG_DIR||cw(EI(),"logs"),yf={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:TI,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},Wc={...yf},_D=(async()=>{try{let{loadConfig:e}=await CI().then(()=>Zm),t=await e({name:"clarity",alias:"logging",defaultConfig:yf,cwd:jc.cwd()});if(t)Object.assign(Wc,t)}catch{}return Wc})();function pr(){if(eo.env.NODE_ENV==="test"||eo.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function AI(){if(eo.env.NODE_ENV==="test"||eo.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof eo<"u"){let e=eo.type;if(e==="renderer"||e==="worker")return!1;return!!(eo.versions&&(eo.versions.node||eo.versions.bun))}return!1}class bf{async format(e){let t=await AI(),r=await this.getMetadata(t);return JSON.stringify({timestamp:e.timestamp.toISOString(),level:e.level,name:e.name,message:e.message,metadata:r})}async getMetadata(e){if(e){let{hostname:t}=await import("os");return{pid:Ws.pid,hostname:t(),environment:Ws.env.NODE_ENV||"development",platform:Ws.platform,version:Ws.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:Ws.env.NODE_ENV||Ws.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}var Cr={red:(e)=>`\x1B[31m${e}\x1B[0m`,green:(e)=>`\x1B[32m${e}\x1B[0m`,yellow:(e)=>`\x1B[33m${e}\x1B[0m`,blue:(e)=>`\x1B[34m${e}\x1B[0m`,magenta:(e)=>`\x1B[35m${e}\x1B[0m`,cyan:(e)=>`\x1B[36m${e}\x1B[0m`,white:(e)=>`\x1B[37m${e}\x1B[0m`,gray:(e)=>`\x1B[90m${e}\x1B[0m`,bgRed:(e)=>`\x1B[41m${e}\x1B[0m`,bgYellow:(e)=>`\x1B[43m${e}\x1B[0m`,bgGray:(e)=>`\x1B[100m${e}\x1B[0m`,bold:(e)=>`\x1B[1m${e}\x1B[0m`,dim:(e)=>`\x1B[2m${e}\x1B[0m`,italic:(e)=>`\x1B[3m${e}\x1B[0m`,underline:(e)=>`\x1B[4m${e}\x1B[0m`,strikethrough:(e)=>`\x1B[9m${e}\x1B[0m`,reset:"\x1B[0m"},ht=Cr,{red:ND,green:kI,yellow:$D,blue:RI,magenta:MD,cyan:LD,white:qm,gray:BD,bgRed:PI,bgYellow:xI,bgGray:jD,bold:Jm,dim:FD,italic:UD,underline:zD,strikethrough:VD,reset:qD}=Cr,zu={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},DI={debug:"\uD83D\uDD0D",info:RI("ℹ"),success:kI("✓"),warning:xI(qm(Jm(" WARN "))),error:PI(qm(Jm(" ERROR ")))};class Xc{name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor(e,t={}){this.name=e,this.config={...Wc},this.options=this.normalizeOptions(t),this.formatter=this.options.formatter||new bf,this.enabled=t.enabled??!0,this.fancy=t.fancy??!0,this.tagFormat=t.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=t.timestampPosition??"right",this.environment=t.environment??vt.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(t);let r={...t},n=t.timestamp!==void 0;if(n)delete r.timestamp;if(this.config={...this.config,...r,timestamp:n||this.config.timestamp,level:this.options.level??"info"},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let i=this.generateKeyId(),o=this.generateKey();this.currentKeyId=i,this.keys.set(i,o),this.encryptionKeys.set(i,{key:o,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed(e){if(!this.fingersCrossedConfig)return!1;let t={debug:0,info:1,success:2,warning:3,error:4},r=this.fingersCrossedConfig.activationLevel??"error";return t[e]>=t[r]}initializeFingersCrossedConfig(e){if(!e.fingersCrossedEnabled&&e.fingersCrossed)return{...zu,...e.fingersCrossed};if(!e.fingersCrossedEnabled)return null;if(!e.fingersCrossed)return{...zu};return{...zu,...e.fingersCrossed}}normalizeOptions(e){let t={format:"json",level:"info",logDirectory:Wc.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},r={...t,...Object.fromEntries(Object.entries(e).filter(([,n])=>n!==void 0))};if(!r.level||!["debug","info","success","warning","error"].includes(r.level))r.level=t.level;return r}shouldWriteToFile(){return!pr()&&this.config.writeToFile===!0}async writeToFile(e){let r=(async()=>{let i,o=0,s=3,c=1000;while(o<s)try{try{try{await mw(this.config.logDirectory,xm.F_OK|xm.W_OK)}catch(a){if(a instanceof Error&&"code"in a)if(a.code==="ENOENT")await fw(this.config.logDirectory,{recursive:!0,mode:493});else if(a.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw a;else throw a}}catch(a){throw console.error("Debug: [writeToFile] Failed to create log directory:",a),a}let l=this.validateEncryptionConfig()?(await this.encrypt(e)).encrypted:Yi.from(e);try{if(!Ec(this.currentLogFile))await Lu(this.currentLogFile,"",{mode:420});if(i=Pm(this.currentLogFile,"a",420),gw(i,l,{flag:"a"}),Rm(i),i!==void 0)Mu(i),i=void 0;if((await qs(this.currentLogFile)).size===0){if(await Lu(this.currentLogFile,l,{flag:"w",mode:420}),(await qs(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(a){let m=a;if(m.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(m.code)){if(o<s-1){let E=typeof m.message==="string"?m.message:"Unknown error";console.error(`Network error during write attempt ${o+1}/${s}:`,E);let k=c*2**o;await new Promise((O)=>setTimeout(O,k)),o++;continue}}if(m?.code&&["ENOSPC","EDQUOT"].includes(m.code))throw Error(`Disk quota exceeded or no space left on device: ${m.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",m),m}finally{if(i!==void 0)try{Mu(i)}catch(a){console.error("Debug: [writeToFile] Error closing file descriptor:",a)}}}catch(l){if(o===s-1){let m=l,E=typeof m.message==="string"?m.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",E),l}o++;let a=c*2**(o-1);await new Promise((m)=>setTimeout(m,a))}})();this.pendingOperations.push(r);let n=this.pendingOperations.length-1;try{await r}catch(i){throw console.error("Debug: [writeToFile] Error in operation:",i),i}finally{this.pendingOperations.splice(n,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return Js(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return Js(this.config.logDirectory,`${this.name}.log`);let e=new Date().toISOString().split("T")[0];return Js(this.config.logDirectory,`${this.name}-${e}.log`)}setupRotation(){if(pr())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let e=this.config.rotation,t;switch(e.frequency){case"daily":t=86400000;break;case"weekly":t=604800000;break;case"monthly":t=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},t)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let t=this.config.rotation.keyRotation;if(!t?.enabled)return;let r=typeof t.interval==="number"?t.interval:60,n=Math.max(r,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((i)=>{console.error("Error rotating keys:",i)})},n)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let t=this.config.rotation.keyRotation,r=this.generateKeyId(),n=this.generateKey();this.currentKeyId=r,this.keys.set(r,n),this.encryptionKeys.set(r,{key:n,createdAt:new Date});let i=Array.from(this.encryptionKeys.entries()).sort(([,c],[,l])=>l.createdAt.getTime()-c.createdAt.getTime()),o=typeof t.maxKeys==="number"?t.maxKeys:1,s=Math.max(1,o);if(i.length>s)for(let[c]of i.slice(s))this.encryptionKeys.delete(c),this.keys.delete(c)}generateKeyId(){return $u(16).toString("hex")}generateKey(){return $u(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let e=this.keys.get(this.currentKeyId);if(!e)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:e,id:this.currentKeyId}}encrypt(e){let{key:t}=this.getCurrentKey(),r=$u(16),n=uw("aes-256-gcm",t,r),i=Yi.isBuffer(e)?e:Yi.from(e,"utf8"),o=n.update(i),s=n.final(),c=o.length+s.length,l=n.getAuthTag(),a=Yi.allocUnsafe(16+c+16);return r.copy(a,0),o.copy(a,16),s.copy(a,16+o.length),l.copy(a,16+c),{encrypted:a,iv:r}}async compressData(e){return new Promise((t,r)=>{let n=Om(),i=[];n.on("data",(o)=>i.push(o)),n.on("end",()=>t(Yi.from(Yi.concat(i)))),n.on("error",r),n.write(e),n.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let e={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let t=this.config.rotation.encrypt;return{...e,...t}}return e}async rotateLog(){if(pr())return;if(!this.shouldWriteToFile())return;let e=await qs(this.currentLogFile).catch(()=>null);if(!e)return;let t=this.config.rotation;if(typeof t==="boolean")return;if(t.maxSize&&e.size>=t.maxSize){let r=this.currentLogFile,n=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let i=await Tc(this.config.logDirectory),o=i.filter((l)=>l.startsWith(this.name)&&/\.log\.\d+$/.test(l)).sort((l,a)=>{let m=Number.parseInt(l.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1]||"0")-m}),s=o.length>0?Number.parseInt(o[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,c=`${r}.${s}`;if(await qs(r).catch(()=>null))try{if(await Dm(r,c),t.compress)try{let l=`${c}.gz`;await this.compressLogFile(c,l),await Ac(c)}catch(l){console.error("Error compressing rotated file:",l)}if(o.length===0&&!i.some((l)=>l.endsWith(".log.1")))try{let l=`${r}.1`;await Lu(l,"")}catch(l){console.error("Error creating backup file:",l)}}catch(l){console.error(`Error during rotation: ${l instanceof Error?l.message:String(l)}`)}}else{let i=new Date().toISOString().replace(/[:.]/g,"-"),o=r.replace(/\.log$/,`-${i}.log`);if(await qs(r).catch(()=>null))await Dm(r,o)}if(this.currentLogFile=n,t.maxFiles){let o=(await Tc(this.config.logDirectory)).filter((s)=>s.startsWith(this.name)).sort((s,c)=>c.localeCompare(s));for(let s of o.slice(t.maxFiles))await Ac(Js(this.config.logDirectory,s))}}}async compressLogFile(e,t){let r=km(e),n=pw(t),i=Om();await bw(r,i,n)}async handleFingersCrossedBuffer(e,t){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed(e)&&!this.isActivated){this.isActivated=!0;for(let r of this.logBuffer){let n=await this.formatter.format(r);if(this.shouldWriteToFile())await this.writeToFile(n);console.log(n)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(t);console.log(t)}}shouldLog(e){if(!this.enabled)return!1;let t={debug:0,info:1,success:2,warning:3,error:4};return t[e]>=t[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map((e)=>{if(e instanceof Promise)return e.catch((t)=>{console.error("Error in pending write operation:",t)});return Promise.resolve()})),Ec(this.currentLogFile))try{let e=Pm(this.currentLogFile,"r+");Rm(e),Mu(e)}catch(e){console.error(`Error flushing file: ${e}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let e of this.pendingOperations)if(typeof e.cancel==="function")e.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch(e){console.error("Error waiting for pending operations:",e)}if(!pr()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let t=(await Tc(this.config.logDirectory)).filter((r)=>(r.includes("temp")||r.includes(".tmp"))&&r.includes(this.name));for(let r of t)try{await Ac(Js(this.config.logDirectory,r))}catch(n){console.error(`Failed to delete temp file ${r}:`,n)}}catch(e){console.error("Error cleaning up temporary files:",e)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag(e){if(!e)return"";return`${this.tagFormat.prefix}${e}${this.tagFormat.suffix}`}formatFileTimestamp(e){return`[${e.toISOString()}]`}formatConsoleTimestamp(e){return this.shouldStyleConsole()?ht.gray(e.toLocaleTimeString()):e.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||pr())return!1;let e=typeof vt.env.NO_COLOR<"u",t=vt.env.FORCE_COLOR==="0";if(e||t)return!1;return!!(typeof vt.stderr<"u"&&vt.stderr.isTTY||typeof vt.stdout<"u"&&vt.stdout.isTTY)}formatConsoleMessage(e){let{timestamp:t,icon:r="",tag:n="",message:i,level:o,showTimestamp:s=!0}=e,c=(O)=>O.replace(this.ANSI_PATTERN,"");if(!this.fancy){let O=[];if(s)O.push(t);if(o==="warning")O.push("WARN");else if(o==="error")O.push("ERROR");else if(r)O.push(r.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(n)O.push(n.replace(/[[\]]/g,""));return O.push(i),O.join(" ")}let l=vt.stdout.columns||120,a="";if(o==="warning"||o==="error")a=`${r} ${i}`;else if(o==="info"||o==="success")a=`${r} ${n} ${i}`;else a=`${r} ${n} ${ht.cyan(i)}`;if(!s)return a.trim();let m=c(a).trim().length,E=c(t).length,k=Math.max(1,l-2-m-E);return`${a.trim()}${" ".repeat(k)}${t}`}formatMessage(e,t){if(t.length===1&&Array.isArray(t[0]))return e.replace(/\{(\d+)\}/g,(o,s)=>{let c=Number.parseInt(s,10);return c<t[0].length?String(t[0][c]):o});let r=/%([sdijfo%])/g,n=0,i=e.replace(r,(o,s)=>{if(s==="%")return"%";if(n>=t.length)return o;let c=t[n++];switch(s){case"s":return String(c);case"d":case"i":return Number(c).toString();case"j":case"o":return JSON.stringify(c,null,2);default:return o}});if(n<t.length)i+=` ${t.slice(n).map((o)=>typeof o==="object"?JSON.stringify(o,null,2):String(o)).join(" ")}`;return i}formatMarkdown(e){if(!e)return e;let t=e;return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(r,n,i)=>{let o=ht.underline(ht.blue(n)),s=this.toAbsoluteFilePath(i);if(s&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let c=`file://${encodeURI(s)}`,l="\x1B]8;;",a="\x1B\\";return`\x1B]8;;${c}\x1B\\${o}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${i}\x1B\\${o}\x1B]8;;\x1B\\`;return o}),t=t.replace(/`([^`]+)`/g,(r,n)=>ht.bgGray(n)),t=t.replace(/\*\*([^*]+)\*\*/g,(r,n)=>ht.bold(n)),t=t.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(r,n)=>ht.italic(n)),t=t.replace(/(?<!_)_([^_]+)_(?!_)/g,(r,n)=>ht.italic(n)),t=t.replace(/~([^~]+)~/g,(r,n)=>ht.strikethrough(n)),t}supportsHyperlinks(){if(pr())return!1;let e=vt.env;if(!e)return!1;if(e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"||e.TERM_PROGRAM==="WezTerm")return!0;if(e.WT_SESSION)return!0;if(e.TERM==="xterm-kitty")return!0;let t=e.VTE_VERSION?Number.parseInt(e.VTE_VERSION,10):0;if(!Number.isNaN(t)&&t>=5000)return!0;return!1}toAbsoluteFilePath(e){try{let t=e;if(t.startsWith("file://"))t=t.replace(/^file:\/\//,"");if(t.startsWith("~")){let r=vt.env.HOME||"";if(r)t=t.replace(/^~(?=$|\/)/,r)}if(hw(t)||t.startsWith("./")||t.startsWith("../"))t=yw(t);else return null;return Ec(t)?t:null}catch{return null}}buildOutputTexts(e){let t=this.shouldStyleConsole()?this.formatMarkdown(e):e,r=e.replace(this.ANSI_PATTERN,"");return{consoleText:t,fileText:r}}async log(e,t,...r){if(!this.shouldLog(e))return;let n=new Date,i=this.formatConsoleTimestamp(n),o=this.formatFileTimestamp(n),s,c;if(t instanceof Error)s=t.message,c=t.stack;else s=this.formatMessage(t,r);let{consoleText:l,fileText:a}=this.buildOutputTexts(s);if(this.shouldStyleConsole()){let E=this.options.showIcons===!1?"":DI[e],k=this.options.showTags!==!1&&this.name?ht.gray(this.formatTag(this.name)):"",O;switch(e){case"debug":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:ht.gray(l),level:e}),console.error(O);break;case"info":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.warn(O);break;case"success":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:ht.green(l),level:e}),console.error(O);break;case"warning":O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.warn(O);break;case"error":if(O=this.formatConsoleMessage({timestamp:i,icon:E,tag:k,message:l,level:e}),console.error(O),c){let q=c.split(`
|
|
99
|
+
`);for(let G of q)if(G.trim()&&!G.includes(s))console.error(this.formatConsoleMessage({timestamp:i,message:ht.gray(` ${G}`),level:e,showTimestamp:!1}))}break}}else if(!pr()){if(console.error(`${o} ${this.environment}.${e.toUpperCase()}: ${s}`),c)console.error(c)}let m=`${o} ${this.environment}.${e.toUpperCase()}: ${a}
|
|
100
|
+
`;if(c)m+=`${c}
|
|
101
|
+
`;if(m=m.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(m)}progress(e,t=""){let r={update:(c,l)=>{},finish:(c)=>{},interrupt:(c,l)=>{}};if(!this.enabled)return r;let n=30;if(this.activeProgressBar={total:Math.max(1,e||1),current:0,message:t||"",barLength:n,lastRenderedLine:""},this.shouldStyleConsole()&&!pr()&&vt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar);return{update:(c,l)=>{if(!this.enabled||!this.activeProgressBar)return;if(this.activeProgressBar.current=Math.min(Math.max(0,c),this.activeProgressBar.total),l!==void 0)this.activeProgressBar.message=l;if(this.shouldStyleConsole()&&!pr()&&vt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)},finish:(c)=>{if(!this.activeProgressBar)return;this.finishProgressBar(this.activeProgressBar,c)},interrupt:(c,l="info")=>{if(!pr()&&vt.stdout.isTTY)vt.stdout.write(`
|
|
102
|
+
`);if(this[l==="warning"?"warn":l](c),this.activeProgressBar&&this.shouldStyleConsole()&&!pr()&&vt.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)}}}time(e){let t=performance.now();if(this.shouldStyleConsole()){let r=this.options.showTags!==!1&&this.name?ht.gray(this.formatTag(this.name)):"",n=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:n,icon:this.options.showIcons===!1?"":ht.blue("◐"),tag:r,message:`${ht.cyan(e)}...`}))}return async(r)=>{if(!this.enabled)return;let n=performance.now(),i=Math.round(n-t),o=`${e} completed in ${i}ms`,s=new Date,c=this.formatConsoleTimestamp(s),a=`${this.formatFileTimestamp(s)} ${this.environment}.INFO: ${o}`;if(r)a+=` ${JSON.stringify(r)}`;if(a+=`
|
|
103
|
+
`,a=a.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let m=this.options.showTags!==!1&&this.name?ht.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:c,icon:this.options.showIcons===!1?"":ht.green("✓"),tag:m,message:`${o}${r?` ${JSON.stringify(r)}`:""}`}))}else if(!pr())console.error(a.trim());if(this.shouldWriteToFile())await this.writeToFile(a)}}async debug(e,...t){await this.log("debug",e,...t)}async info(e,...t){await this.log("info",e,...t)}async success(e,...t){await this.log("success",e,...t)}async warn(e,...t){await this.log("warning",e,...t)}async error(e,...t){await this.log("error",e,...t)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let e=this.config.rotation,{encrypt:t}=e;return!!t}async only(e){if(!this.enabled)return;return await e()}isEnabled(){return this.enabled}setEnabled(e){this.enabled=e}extend(e){let t=`${this.name}:${e}`,r=new Xc(t,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(r),r}createReadStream(){if(pr())throw Error("createReadStream is not supported in browser environments");if(!Ec(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return km(this.currentLogFile,{encoding:"utf8"})}async decrypt(e){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let t=this.config.rotation;if(!t.encrypt||typeof t.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let r=this.keys.get(this.currentKeyId);try{let n=Yi.isBuffer(e)?e:Yi.from(e,"base64"),i=n.subarray(0,16),o=n.subarray(n.length-16),s=n.subarray(16,n.length-16),c=lw("aes-256-gcm",r,i);c.setAuthTag(o);let l=c.update(s),a=c.final(),m=l.length+a.length,E=Yi.allocUnsafe(m);return l.copy(E,0),a.copy(E,l.length),E.toString("utf8")}catch(n){throw Error(`Decryption failed: ${n instanceof Error?n.message:String(n)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return pr()}isServerMode(){return!pr()}setTestEncryptionKey(e,t){this.currentKeyId=e,this.keys.set(e,t)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box(e){if(!this.enabled)return;let t=new Date,r=this.formatConsoleTimestamp(t),n=this.formatFileTimestamp(t),{consoleText:i,fileText:o}=this.buildOutputTexts(e);if(this.shouldStyleConsole()){let c=i.split(`
|
|
104
|
+
`),l=Math.max(...c.map((k)=>k.length))+2,a=`┌${"─".repeat(l)}┐`,m=`└${"─".repeat(l)}┘`,E=c.map((k)=>this.formatConsoleMessage({timestamp:r,message:ht.cyan(k),showTimestamp:!1}));console.error(this.formatConsoleMessage({timestamp:r,message:ht.cyan(a),showTimestamp:!1})),E.forEach((k)=>console.error(k)),console.error(this.formatConsoleMessage({timestamp:r,message:ht.cyan(m),showTimestamp:!1}))}else if(!pr())console.error(`${n} ${this.environment}.INFO: [BOX] ${o}`);let s=`${n} ${this.environment}.INFO: [BOX] ${o}
|
|
105
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(s)}async prompt(e){if(pr())return Promise.resolve(!0);return new Promise((t)=>{console.error(`${ht.cyan("?")} ${e} (y/n) `);let r=(n)=>{let i=n.toString().trim().toLowerCase();vt.stdin.removeListener("data",r);try{if(typeof vt.stdin.setRawMode==="function")vt.stdin.setRawMode(!1)}catch{}vt.stdin.pause(),console.error(""),t(i==="y"||i==="yes")};try{if(typeof vt.stdin.setRawMode==="function")vt.stdin.setRawMode(!0)}catch{}vt.stdin.resume(),vt.stdin.once("data",r)})}setFancy(e){this.fancy=e}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start(e,...t){if(!this.enabled)return;let r=e;if(t&&t.length>0){let l=/%([sdijfo%])/g,a=0;if(r=e.replace(l,(m,E)=>{if(E==="%")return"%";if(a>=t.length)return m;let k=t[a++];switch(E){case"s":return String(k);case"d":case"i":return Number(k).toString();case"j":case"o":return JSON.stringify(k,null,2);default:return m}}),a<t.length)r+=` ${t.slice(a).map((m)=>typeof m==="object"?JSON.stringify(m,null,2):String(m)).join(" ")}`}let{consoleText:n,fileText:i}=this.buildOutputTexts(r);if(this.shouldStyleConsole()){let l=this.options.showTags!==!1&&this.name?ht.gray(this.formatTag(this.name)):"",a=this.options.showIcons===!1?"":`${ht.blue("◐")} `;console.error(`${a}${l} ${ht.cyan(n)}`)}let c=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${i}
|
|
106
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(c)}renderProgressBar(e,t=!1){if(!this.enabled||!this.shouldStyleConsole()||!vt.stdout.isTTY)return;let r=Math.min(100,Math.max(0,Math.round(e.current/e.total*100))),n=Math.round(e.barLength*r/100),i=e.barLength-n,o=ht.green("━".repeat(n)),s=ht.gray("━".repeat(i)),c=`[${o}${s}]`,l=`${r}%`.padStart(4),a=e.message?` ${e.message}`:"",m=this.options.showIcons===!1?"":t||r===100?ht.green("✓"):ht.blue("▶"),E=this.options.showTags!==!1&&this.name?` ${ht.gray(this.formatTag(this.name))}`:"",k=`\r${m}${E} ${c} ${l}${a}`,O=vt.stdout.columns||80,q=" ".repeat(Math.max(0,O-k.replace(this.ANSI_PATTERN,"").length));if(e.lastRenderedLine=`${k}${q}`,vt.stdout.write(e.lastRenderedLine),t)vt.stdout.write(`
|
|
107
|
+
`)}finishProgressBar(e,t){if(!this.enabled||!this.fancy||pr()||!vt.stdout.isTTY){this.activeProgressBar=null;return}if(e.current<e.total)e.current=e.total;if(t)e.message=t;this.renderProgressBar(e,!0),this.activeProgressBar=null}async clear(e={}){if(pr()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let t=await Tc(this.config.logDirectory),r=[];for(let n of t){if(!(e.name?new RegExp(e.name.replace("*",".*")).test(n):n.startsWith(this.name))||!n.endsWith(".log"))continue;let o=Js(this.config.logDirectory,n);if(e.before)try{if((await qs(o)).mtime>=e.before)continue}catch(s){console.error(`Failed to get stats for file ${o}:`,s);continue}r.push(o)}if(r.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${r.length} log file(s)...`);for(let n of r)try{await Ac(n),console.warn(`Deleted log file: ${n}`)}catch(i){console.error(`Failed to delete log file ${n}:`,i)}console.warn("Log clearing process finished.")}catch(t){console.error("Error during log clearing process:",t)}}}var JD=new Xc("stacks");class yi extends Error{timestamp;context;constructor(e,t={}){super(e);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=t,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let e=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([t,r])=>`${t}: ${r}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${e}`}}class Sf extends yi{code="CONFIG_NOT_FOUND";constructor(e,t,r){let n=r===void 0?[]:Array.isArray(r)?r.filter(Boolean):[r],i="";if(n.length===1)i=` or alias "${n[0]}"`;else if(n.length>1)i=` or aliases ${n.map((o)=>`"${o}"`).join(", ")}`;super(`Configuration "${e}"${i} not found`,{configName:e,alias:r,searchPaths:t,searchPathCount:t.length})}}class Hc extends yi{code="CONFIG_LOAD_ERROR";constructor(e,t,r){super(`Failed to load configuration from "${e}": ${t.message}`,{configPath:e,configName:r,originalError:t.name,originalMessage:t.message});this.cause=t}}class vf extends yi{code="CONFIG_VALIDATION_ERROR";constructor(e,t,r){super(`Configuration validation failed for "${e}"`,{configPath:e,configName:r,validationErrors:t,errorCount:t.length})}}class wf extends yi{code="CONFIG_MERGE_ERROR";constructor(e,t,r,n){super(`Failed to merge configuration from "${e}" with "${t}": ${r.message}`,{sourcePath:e,targetPath:t,configName:n,originalError:r.name,originalMessage:r.message});this.cause=r}}class ul extends yi{code="ENV_VAR_ERROR";constructor(e,t,r,n){super(`Failed to parse environment variable "${e}" with value "${t}" as ${r}`,{envKey:e,envValue:t,expectedType:r,configName:n})}}class If extends yi{code="FILE_SYSTEM_ERROR";constructor(e,t,r){super(`File system ${e} failed for "${t}": ${r.message}`,{operation:e,path:t,originalError:r.name,originalMessage:r.message});this.cause=r}}class Cf extends yi{code="TYPE_GENERATION_ERROR";constructor(e,t,r){super(`Failed to generate types from "${e}" to "${t}": ${r.message}`,{configDir:e,outputPath:t,originalError:r.name,originalMessage:r.message});this.cause=r}}class Gc extends yi{code="SCHEMA_VALIDATION_ERROR";constructor(e,t,r){super(`Schema validation failed${r?` for config "${r}"`:""}`,{schemaPath:e,configName:r,validationErrors:t,errorCount:t.length})}}class Ef extends yi{code="BROWSER_CONFIG_ERROR";constructor(e,t,r,n){super(`Failed to fetch configuration from "${e}": ${t} ${r}`,{endpoint:e,status:t,statusText:r,configName:n})}}class Tf extends yi{code="PLUGIN_ERROR";constructor(e,t,r){super(`Plugin "${e}" failed during ${t}: ${r.message}`,{pluginName:e,operation:t,originalError:r.name,originalMessage:r.message});this.cause=r}}var ss={configNotFound(e,t,r){return new Sf(e,t,r)},configLoad(e,t,r){return new Hc(e,t,r)},configValidation(e,t,r){return new vf(e,t,r)},configMerge(e,t,r,n){return new wf(e,t,r,n)},envVar(e,t,r,n){return new ul(e,t,r,n)},fileSystem(e,t,r){return new If(e,t,r)},typeGeneration(e,t,r){return new Cf(e,t,r)},schemaValidation(e,t,r){return new Gc(e,t,r)},browserConfig(e,t,r,n){return new Ef(e,t,r,n)},plugin(e,t,r){return new Tf(e,t,r)}};async function OI(e,t={}){let{maxRetries:r=3,retryDelay:n=1000,isRetryable:i=()=>!0,fallback:o}=t,s=Error("Unknown error occurred");for(let c=0;c<=r;c++)try{return await e()}catch(l){if(s=l instanceof Error?l:Error(String(l)),c===r||!i(s))break;if(n>0)await new Promise((a)=>setTimeout(a,n))}if(o!==void 0)return o;throw s instanceof Error?s:Error(`Unknown error: ${String(s)}`)}class ll{defaultParsers;constructor(){this.defaultParsers=[{name:"boolean",canParse:(e,t)=>t==="boolean"||["true","false","1","0","yes","no"].includes(e.toLowerCase()),parse:(e)=>{let t=e.toLowerCase();return["true","1","yes"].includes(t)}},{name:"number",canParse:(e,t)=>t==="number"||!Number.isNaN(Number(e))&&!Number.isNaN(Number.parseFloat(e)),parse:(e)=>{let t=Number(e);if(Number.isNaN(t))throw TypeError(`Cannot parse "${e}" as number`);return t}},{name:"array",canParse:(e,t)=>t==="array"||e.startsWith("[")||e.includes(","),parse:(e)=>{try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return e.split(",").map((t)=>t.trim())}},{name:"json",canParse:(e,t)=>t==="object"||(e.startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]")),parse:(e)=>{try{return JSON.parse(e)}catch(t){throw Error(`Cannot parse "${e}" as JSON: ${t}`)}}}]}async applyEnvironmentVariables(e,t,r={}){let{prefix:n,useCamelCase:i=!0,useBackwardCompatibility:o=!0,customParsers:s={},verbose:c=!1,trackPerformance:l=!0}=r,a=async()=>{if(!e)return{config:t,source:{type:"environment",priority:50,timestamp:new Date}};let m=n||this.generateEnvPrefix(e),E={...t};return this.processObject(E,[],m,{useCamelCase:i,useBackwardCompatibility:o,customParsers:s,verbose:c,configName:e}),{config:E,source:{type:"environment",priority:50,timestamp:new Date}}};if(l)return rl.track("applyEnvironmentVariables",a,{configName:e});return a()}generateEnvPrefix(e){return e.toUpperCase().replace(/-/g,"_")}formatEnvKey(e,t){if(!t)return e.toUpperCase();return e.replace(/([A-Z])/g,"_$1").toUpperCase()}processObject(e,t,r,n){for(let[i,o]of Object.entries(e)){let s=[...t,i],c=s.map((m)=>this.formatEnvKey(m,n.useCamelCase)),l=`${r}_${c.join("_")}`,a=n.useBackwardCompatibility?`${r}_${s.map((m)=>m.toUpperCase()).join("_")}`:null;if(n.verbose);if(typeof o==="object"&&o!==null&&!Array.isArray(o))this.processObject(o,s,r,n);else{let m=Rc.env[l]||(a?Rc.env[a]:void 0);if(m!==void 0){if(n.verbose){let E=Rc.env[l]?l:a}try{e[i]=this.parseEnvironmentValue(m,typeof o,l,n.customParsers,n.configName)}catch(E){if(E instanceof ul)throw E;throw ss.envVar(l,m,typeof o,n.configName)}}}}}parseEnvironmentValue(e,t,r,n,i){for(let[o,s]of Object.entries(n))try{return s(e)}catch{continue}for(let o of this.defaultParsers)if(o.canParse(e,t))try{return o.parse(e)}catch{throw ss.envVar(r,e,`${t} (via ${o.name} parser)`,i)}return e}getEnvironmentVariables(e){let t={},r=e.toUpperCase();for(let[n,i]of Object.entries(Rc.env))if(n.startsWith(r)&&i!==void 0)t[n]=i;return t}validateEnvironmentVariable(e,t,r){let n=[];if(!/^[A-Z_][A-Z0-9_]*$/.test(e))n.push(`Environment variable key "${e}" should only contain uppercase letters, numbers, and underscores`);if(r)try{this.parseEnvironmentValue(e,t,r,{})}catch(i){n.push(`Cannot parse value "${t}" as ${r}: ${i}`)}return{isValid:n.length===0,errors:n}}generateEnvVarDocs(e,t,r={}){let{prefix:n,format:i="text"}=r,o=n||this.generateEnvPrefix(e),s=[];switch(this.extractEnvVarInfo(t,[],o,s),i){case"markdown":return this.formatAsMarkdown(s,e);case"json":return JSON.stringify(s,null,2);default:return this.formatAsText(s,e)}}extractEnvVarInfo(e,t,r,n){for(let[i,o]of Object.entries(e)){let s=[...t,i],c=`${r}_${s.map((l)=>this.formatEnvKey(l,!0)).join("_")}`;if(typeof o==="object"&&o!==null&&!Array.isArray(o))this.extractEnvVarInfo(o,s,r,n);else n.push({key:c,type:Array.isArray(o)?"array":typeof o,description:`Configuration for ${s.join(".")}`,example:this.generateExample(o)})}}generateExample(e){if(Array.isArray(e))return JSON.stringify(e);if(typeof e==="object"&&e!==null)return JSON.stringify(e);return String(e)}formatAsText(e,t){let r=`Environment Variables for ${t}:
|
|
108
|
+
|
|
109
|
+
`;for(let n of e)r+=`${n.key}
|
|
110
|
+
`,r+=` Type: ${n.type}
|
|
111
|
+
`,r+=` Description: ${n.description}
|
|
112
|
+
`,r+=` Example: ${n.example}
|
|
113
|
+
|
|
114
|
+
`;return r}formatAsMarkdown(e,t){let r=`# Environment Variables for ${t}
|
|
115
|
+
|
|
116
|
+
`;r+=`| Variable | Type | Description | Example |
|
|
117
|
+
`,r+=`|----------|------|-------------|----------|
|
|
118
|
+
`;for(let n of e)r+=`| \`${n.key}\` | ${n.type} | ${n.description} | \`${n.example}\` |
|
|
119
|
+
`;return r}}function _I(e,t,r={}){return Af(e,t,r,new WeakMap)}function Af(e,t,r,n){let{arrayMergeMode:i="replace",skipNullish:o=!1,customMerger:s}=r;if(t===null||t===void 0)return o?e:t;if(s){let c=s(e,t);if(c!==void 0)return c}if(Array.isArray(t)||Array.isArray(e))return kf(e,t,i,n);if(!di(t)||!di(e))return t;return LI(e,t,r,n)}function kf(e,t,r,n){if(Array.isArray(t)&&!Array.isArray(e))return t;if(Array.isArray(e)&&!Array.isArray(t))return t;if(Array.isArray(t)&&Array.isArray(e))switch(r){case"replace":return t;case"concat":return NI(e,t);case"smart":return $I(e,t,n);default:return t}return t}function NI(e,t){let r=[...t];for(let n of e)if(!r.some((i)=>tl(i,n)))r.push(n);return r}function $I(e,t,r){if(t.length===0)return e;if(e.length===0)return t;if(di(t[0])&&di(e[0]))return MI(e,t,r);if(t.every((n)=>typeof n==="string")&&e.every((n)=>typeof n==="string")){let n=[...t];for(let i of e)if(!n.includes(i))n.push(i);return n}return t}function MI(e,t,r){let n=[...t];for(let i of e){if(!di(i)){n.push(i);continue}let o=["id","name","key","path","type"],s=!1;for(let c of o)if(c in i){if(n.find((a)=>di(a)&&(c in a)&&a[c]===i[c])){s=!0;break}}if(!s)n.push(i)}return n}function LI(e,t,r,n){let i=t;if(di(i)&&n.has(i))return n.get(i);let o={...e};if(di(i))n.set(i,o);for(let s in i){if(!Object.prototype.hasOwnProperty.call(i,s))continue;let c=i[s],l=o[s];if(r.skipNullish&&(c===null||c===void 0))continue;if(c===null||c===void 0){o[s]=c;continue}if(di(c)&&di(l))o[s]=Af(l,c,r,n);else if(Array.isArray(c)||Array.isArray(l))o[s]=kf(l,c,r.arrayMergeMode||"smart",n);else o[s]=c}return o}function Rf(e,t,r="replace"){return _I(e,t,{arrayMergeMode:r==="replace"?"replace":"smart",skipNullish:!0})}function tl(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!tl(e[r],t[r]))return!1;return!0}if(di(e)&&di(t)){let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let i of r){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!tl(e[i],t[i]))return!1}return!0}return!1}function di(e){return Boolean(e&&typeof e==="object"&&!Array.isArray(e))}class Pf{extensions=Km;async loadFromPath(e,t,r={}){let{arrayStrategy:n="replace",useCache:i=!0,cacheTtl:o,trackPerformance:s=!0,verbose:c=!1}=r;if(i){let a=$c.getWithFileCheck("file",e);if(a){if(c)console.log(`Configuration loaded from cache: ${e}`);return a}}let l=async()=>{if(!Pc(e))return null;try{let a=`?t=${Date.now()}`,m=await import(e+a),E=m.default||m,k="default"in m,O=Object.keys(m).length>0;if(!k&&!O)throw new Hc(e,Error("Configuration file is empty and exports nothing"),"unknown");if(typeof E!=="object"||E===null||Array.isArray(E))throw new Hc(e,Error("Configuration must export a valid object"),"unknown");let Y={config:Rf(t,E,n),source:{type:"file",path:e,priority:100,timestamp:new Date}};if(i)$c.setWithFileCheck("file",Y,e,o);return Y}catch(a){throw a instanceof Error?ss.configLoad(e,a):ss.configLoad(e,Error(String(a)))}};if(s)return rl.track("loadFromPath",l,{path:e});return l()}async tryLoadFromPaths(e,t,r={}){for(let n of e)try{let i=await this.loadFromPath(n,t,r);if(i)return i}catch(i){if(i instanceof Error&&i.name==="ConfigLoadError")throw i;if(r.verbose)console.warn(`Failed to load config from ${n}:`,i)}return null}generateConfigPaths(e,t,r){return Dv({name:e,directory:t,alias:r})}generateNamePatterns(e,t){return Qm({name:e,alias:t})}checkFileAccess(e){return OI(async()=>Pc(e),{maxRetries:2,retryDelay:100,fallback:!1})}async discoverConfigFiles(e,t,r){let n=[];if(!Pc(e))return n;if(t||r){let i=this.generateNamePatterns(t||"",r);for(let o of i)for(let s of this.extensions){let c=Wm(e,`${o}${s}`);if(await this.checkFileAccess(c))n.push(c)}}else try{let{readdirSync:i}=await import("fs"),o=i(e);for(let s of o)if(this.looksLikeConfigFile(s)){let c=Wm(e,s);if(await this.checkFileAccess(c))n.push(c)}}catch{return[]}return n}looksLikeConfigFile(e){return[/\.config\.(ts|js|mjs|cjs|json|mts|cts)$/,/^\..*\.(ts|js|mjs|cjs|json|mts|cts)$/,/config\.(ts|js|mjs|cjs|json|mts|cts)$/].some((r)=>r.test(e))}async validateConfigFile(e){let t=[];try{if(!Pc(e))return t.push("Configuration file does not exist"),t;let r=await import(e),n=r.default||r;if(n===void 0)t.push("Configuration file must export a default value or named exports");else if(typeof n!=="object"||n===null)t.push("Configuration must be an object");else if(Array.isArray(n))t.push("Configuration cannot be an array at the root level");if(e.endsWith(".json"))try{let{readFileSync:i}=await import("fs"),o=i(e,"utf8");JSON.parse(o)}catch(i){t.push(`Invalid JSON syntax: ${i}`)}}catch(r){t.push(`Failed to load configuration file: ${r}`)}return t}async getFileModificationTime(e){try{let{statSync:t}=await import("fs");return t(e).mtime}catch{return null}}async preloadConfigurations(e,t={}){let r=new Map;return await Promise.allSettled(e.map(async(n)=>{try{let i=await this.loadFromPath(n,{},t);if(i)r.set(n,i.config)}catch(i){if(t.verbose)console.warn(`Failed to preload ${n}:`,i)}})),r}}var jI=/^https?:\/\//;class xf{async validateConfiguration(e,t,r={}){let{stopOnFirstError:n=!1,validateRequired:i=!0,validateTypes:o=!0,customRules:s=[],trackPerformance:c=!0,verbose:l=!1}=r,a=async()=>{let m=[],E=[],k={stopOnFirstError:n,validateRequired:i,validateTypes:o,customRules:s,trackPerformance:c,verbose:l};try{if(typeof t==="string")return await this.validateWithSchemaFile(e,t,k);else if(Array.isArray(t))return this.validateWithRules(e,[...t,...s],k);else return this.validateWithJSONSchema(e,t,k)}catch(O){return m.push({path:"",message:`Validation failed: ${O}`,rule:"system"}),{isValid:!1,errors:m,warnings:E}}};if(c)return await rl.track("validateConfiguration",a);return a()}async validateWithSchemaFile(e,t,r){try{if(!BI(t))throw new Gc(t,[{path:"",message:"Schema file does not exist"}]);let n=await import(t),i=n.default||n;if(Array.isArray(i))return this.validateWithRules(e,i,r);else return this.validateWithJSONSchema(e,i,r)}catch(n){throw new Gc(t,[{path:"",message:`Failed to load schema: ${n}`}])}}validateWithJSONSchema(e,t,r){let n=[],i=[];return this.validateObjectAgainstSchema(e,t,"",n,i,r),{isValid:n.length===0,errors:n,warnings:i}}validateObjectAgainstSchema(e,t,r,n,i,o){if(o.validateTypes&&t.type){let s=Array.isArray(e)?"array":typeof e,c=Array.isArray(t.type)?t.type:[t.type];if(!c.includes(s)){if(n.push({path:r,message:`Expected type ${c.join(" or ")}, got ${s}`,expected:c.join(" or "),actual:s,rule:"type"}),o.stopOnFirstError)return}}if(t.enum&&!t.enum.includes(e)){if(n.push({path:r,message:`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"}),o.stopOnFirstError)return}if(typeof e==="string"){if(t.minLength!==void 0&&e.length<t.minLength)n.push({path:r,message:`String length must be at least ${t.minLength}`,expected:`>= ${t.minLength}`,actual:e.length,rule:"minLength"});if(t.maxLength!==void 0&&e.length>t.maxLength)n.push({path:r,message:`String length must not exceed ${t.maxLength}`,expected:`<= ${t.maxLength}`,actual:e.length,rule:"maxLength"});if(t.pattern){if(!new RegExp(t.pattern).test(e))n.push({path:r,message:`String does not match pattern ${t.pattern}`,expected:t.pattern,actual:e,rule:"pattern"})}}if(typeof e==="number"){if(t.minimum!==void 0&&e<t.minimum)n.push({path:r,message:`Value must be at least ${t.minimum}`,expected:`>= ${t.minimum}`,actual:e,rule:"minimum"});if(t.maximum!==void 0&&e>t.maximum)n.push({path:r,message:`Value must not exceed ${t.maximum}`,expected:`<= ${t.maximum}`,actual:e,rule:"maximum"})}if(Array.isArray(e)&&t.items)for(let s=0;s<e.length;s++){let c=r?`${r}[${s}]`:`[${s}]`;if(this.validateObjectAgainstSchema(e[s],t.items,c,n,i,o),o.stopOnFirstError&&n.length>0)return}if(e&&typeof e==="object"&&!Array.isArray(e)){let s=e;if(o.validateRequired&&t.required){for(let c of t.required)if(!(c in s)){if(n.push({path:r?`${r}.${c}`:c,message:`Missing required property '${c}'`,expected:"required",rule:"required"}),o.stopOnFirstError)return}}if(t.properties){for(let[c,l]of Object.entries(t.properties))if(c in s){let a=r?`${r}.${c}`:c;if(this.validateObjectAgainstSchema(s[c],l,a,n,i,o),o.stopOnFirstError&&n.length>0)return}}if(t.additionalProperties===!1){let c=new Set(Object.keys(t.properties||{}));for(let l of Object.keys(s))if(!c.has(l))i.push({path:r?`${r}.${l}`:l,message:`Additional property '${l}' is not allowed`,rule:"additionalProperties"})}}}validateWithRules(e,t,r){let n=[],i=[];for(let o of t)try{let s=this.getValueByPath(e,o.path),c=this.validateWithRule(s,o,o.path);if(n.push(...c),r.stopOnFirstError&&n.length>0)break}catch(s){n.push({path:o.path,message:`Rule validation failed: ${s}`,rule:"system"})}return{isValid:n.length===0,errors:n,warnings:i}}validateWithRule(e,t,r){let n=[];if(t.required&&(e===void 0||e===null))return n.push({path:r,message:t.message||`Property '${r}' is required`,expected:"required",rule:"required"}),n;if(e===void 0||e===null)return n;if(t.type){let i=Array.isArray(e)?"array":typeof e;if(i!==t.type)n.push({path:r,message:t.message||`Expected type ${t.type}, got ${i}`,expected:t.type,actual:i,rule:"type"})}if(t.min!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i<t.min)n.push({path:r,message:t.message||`Value must be at least ${t.min}`,expected:`>= ${t.min}`,actual:i,rule:"min"})}if(t.max!==void 0){let i=Array.isArray(e)?e.length:typeof e==="string"?e.length:typeof e==="number"?e:0;if(i>t.max)n.push({path:r,message:t.message||`Value must not exceed ${t.max}`,expected:`<= ${t.max}`,actual:i,rule:"max"})}if(t.pattern&&typeof e==="string"){if(!t.pattern.test(e))n.push({path:r,message:t.message||`Value does not match pattern ${t.pattern}`,expected:t.pattern.toString(),actual:e,rule:"pattern"})}if(t.enum&&!t.enum.includes(e))n.push({path:r,message:t.message||`Value must be one of: ${t.enum.join(", ")}`,expected:t.enum.join(", "),actual:e,rule:"enum"});if(t.validator){let i=t.validator(e);if(i)n.push({path:r,message:t.message||i,rule:"custom"})}return n}getValueByPath(e,t){if(!t)return e;let r=t.split("."),n=e;for(let i of r)if(n&&typeof n==="object"&&i in n)n=n[i];else return;return n}generateRulesFromInterface(e){let t=[],r=e.matchAll(/(\w+)(\?)?:\s*(\w+)/g);for(let n of r){let[,i,o,s]=n;t.push({path:i,required:!o,type:this.mapTypeScriptType(s)})}return t}mapTypeScriptType(e){switch(e.toLowerCase()){case"string":return"string";case"number":return"number";case"boolean":return"boolean";case"array":return"array";case"object":return"object";default:return"object"}}static createCommonRules(){return{server:[{path:"port",required:!0,type:"number",min:1,max:65535},{path:"host",required:!0,type:"string",min:1},{path:"ssl",type:"boolean"}],database:[{path:"url",required:!0,type:"string",min:1},{path:"pool",type:"number",min:1,max:100},{path:"timeout",type:"number",min:0}],api:[{path:"baseUrl",required:!0,type:"string",pattern:jI},{path:"timeout",type:"number",min:0},{path:"retries",type:"number",min:0,max:10}]}}}var fi=new Xc("bunfig",{showTags:!0});function FI(e){if(!e)return"";let t=Array.isArray(e)?e.filter(Boolean):[e];if(t.length===0)return"";if(t.length===1)return` or alias "${t[0]}"`;return` or aliases ${t.map((r)=>`"${r}"`).join(", ")}`}class Df{fileLoader=new Pf;envProcessor=new ll;validator=new xf;async loadConfig(e){let t=Date.now(),{cache:r,performance:n,schema:i,validate:o,...s}=e;try{if(r?.enabled){let l=this.checkCache(s.name||"",s);if(l)return l}let c;try{c=await this.loadConfigurationStrategies(s,!0,r)}catch(l){if(s.configFile)throw l;let a=s.__strictErrorHandling;if(l instanceof Error&&l.name==="ConfigNotFoundError"){if(a)throw l;c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`No configuration file found for "${s.name||"config"}", using defaults with environment variables`]}}else if(l instanceof Error&&l.name==="ConfigLoadError"){let m=l.message.includes("EACCES")||l.message.includes("EPERM")||l.message.includes("permission denied"),E=!m&&(l.message.includes("syntax")||l.message.includes("Expected")||l.message.includes("Unexpected")||l.message.includes("BuildMessage")||l.message.includes("errors building")),k=l.message.includes("Configuration must export a valid object")||l.message.includes("Configuration file is empty and exports nothing");if(a&&(k||m))throw l;if(E&&(!a||!k))c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:["Configuration file has syntax errors, using defaults with environment variables"]};else if(!a)c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`Configuration loading error, using defaults: ${l.message}`]};else throw l}else c={...await this.applyEnvironmentVariables(s.name||"",s.defaultConfig,s.checkEnv!==!1,s.verbose||!1),warnings:[`Configuration loading failed, using defaults: ${l instanceof Error?l.message:String(l)}`]}}if(i||o)await this.validateConfiguration(c.config,i,o,s.name);if(r?.enabled&&c)this.cacheResult(s.name||"",c,r,s);if(n?.enabled){let l={operation:"loadConfig",duration:Date.now()-t,configName:s.name,timestamp:new Date};if(n.onMetrics)n.onMetrics(l);if(n.slowThreshold&&l.duration>n.slowThreshold)fi.warn(`Slow configuration loading detected: ${l.duration}ms for ${s.name}`);c.metrics=l}return c}catch(c){if(c instanceof Error&&c.name==="ConfigNotFoundError")throw c;let l=Date.now()-t;throw fi.error(`Configuration loading failed after ${l}ms:`,[c instanceof Error?c:Error(String(c))]),c}}async loadConfigurationStrategies(e,t=!1,r){let{name:n="",alias:i,configFile:o,cwd:s,configDir:c,defaultConfig:l,checkEnv:a=!0,arrayStrategy:m="replace",verbose:E=!1}=e,k=s||Kc.cwd(),O=[];if(o){let he=Mi(k,o);O.push(he);let ee=a?Ca(n,l,E):l,Re=await this.fileLoader.tryLoadFromPaths([he],ee,{arrayStrategy:m,verbose:E,cacheTtl:r?.ttl,useCache:!r?.ttl||r.ttl>100});if(!Re)throw ss.configNotFound(n||o,O,i);if(E)fi.success(`Configuration loaded from explicit path: ${he}`);return this.finalizeResult(Re,O,a,n,E)}let q=await this.loadLocalConfiguration(n,i,k,c,l,m,E,a,r);if(q)return O.push(...this.getLocalSearchPaths(n,i,k,c)),this.finalizeResult(q,O,a,n,E);let G=await this.loadHomeConfiguration(n,i,l,m,E,a);if(G)return O.push(...this.getHomeSearchPaths(n,i)),this.finalizeResult(G,O,a,n,E);let Y=await this.loadPackageJsonConfiguration(n,i,k,l,m,E,a);if(Y)return O.push(Mi(k,"package.json")),this.finalizeResult(Y,O,a,n,E);if(O.push(...this.getAllSearchPaths(n,i,k,c)),t)throw ss.configNotFound(n,O,i);return{...await this.applyEnvironmentVariables(n,l,a,E),warnings:[`No configuration file found for "${n}"${FI(i)}, using defaults with environment variables`]}}async loadLocalConfiguration(e,t,r,n,i,o,s,c,l){let a=c?Ca(e,i,s):i,m=this.getLocalDirectories(r,n);for(let E of m){if(s)fi.info(`Searching for configuration in: ${E}`);let k=this.fileLoader.generateConfigPaths(e,E,t),O=await this.fileLoader.tryLoadFromPaths(k,a,{arrayStrategy:o,verbose:s,cacheTtl:l?.ttl,useCache:!l?.ttl||l.ttl>100});if(O){if(s)fi.success(`Configuration loaded from: ${O.source.path}`);return O}}return null}async loadHomeConfiguration(e,t,r,n,i,o){if(!e)return null;let s=o?Ca(e,r,i):r,c=[Mi(Ms(),".config",e),Mi(Ms(),".config"),Ms()];for(let l of c){if(i)fi.info(`Checking home directory: ${l}`);let a=this.fileLoader.generateConfigPaths(e,l,t),m=await this.fileLoader.tryLoadFromPaths(a,s,{arrayStrategy:n,verbose:i});if(m){if(i)fi.success(`Configuration loaded from home directory: ${m.source.path}`);return m}}return null}async loadPackageJsonConfiguration(e,t,r,n,i,o,s){let c=s?Ca(e,n,o):n;try{let l=Mi(r,"package.json");if(!_v(l))return null;let a={};try{a=JSON.parse(Nv(l,"utf8"))}catch(k){if(o)fi.warn("Failed to parse package.json:",[k instanceof Error?k:Error(String(k))]);return null}let m=a[e],E=e;if(!m&&t){let k=Array.isArray(t)?t:[t];for(let O of k){if(!O)continue;if(a[O]){m=a[O],E=O;break}}}if(m&&typeof m==="object"&&!Array.isArray(m)){if(o)fi.success(`Configuration loaded from package.json: ${E}`);return{config:Rf(c,m,i),source:{type:"package.json",path:l,priority:30,timestamp:new Date}}}}catch(l){if(o)fi.warn("Failed to load package.json:",[l instanceof Error?l:Error(String(l))])}return null}async applyEnvironmentVariables(e,t,r,n){if(!r||!e||typeof t!=="object"||t===null||Array.isArray(t))return{config:t,source:{type:"default",priority:10,timestamp:new Date}};return{config:Ca(e,t,n),source:{type:"environment",priority:20,timestamp:new Date}}}async finalizeResult(e,t,r,n,i){return{config:e.config,source:e.source,path:e.source.path}}async validateConfiguration(e,t,r,n){let i=[];if(r){let o=r(e);if(o)i.push(...o)}if(t){let o=await this.validator.validateConfiguration(e,t);if(!o.isValid)i.push(...o.errors.map((s)=>s.path?`${s.path}: ${s.message}`:s.message))}if(i.length>0)throw ss.configValidation(n||"unknown",i,n)}checkCache(e,t){let r=this.generateCacheKey(e,t);return $c.get(r)||null}cacheResult(e,t,r,n){let i=this.generateCacheKey(e,n);$c.set(i,t,void 0,r.ttl)}generateCacheKey(e,t){let r=[e];if(t.alias){let n=Array.isArray(t.alias)?t.alias.join(","):t.alias;r.push(`alias:${n}`)}if(t.cwd)r.push(`cwd:${t.cwd}`);if(t.configFile)r.push(`configFile:${t.configFile}`);if(t.configDir)r.push(`configDir:${t.configDir}`);if("checkEnv"in t)r.push(`checkEnv:${t.checkEnv}`);return r.join("|")}getLocalDirectories(e,t){return Ov({cwd:e,configDir:t})}getAllSearchPaths(e,t,r,n){let i=[];return i.push(...this.getLocalSearchPaths(e,t,r,n)),i.push(...this.getHomeSearchPaths(e,t)),i.push(Mi(r,"package.json")),i}getLocalSearchPaths(e,t,r,n){let i=this.getLocalDirectories(r,n),o=[];for(let s of i)o.push(...this.fileLoader.generateConfigPaths(e,s,t));return o}getHomeSearchPaths(e,t){if(!e)return[];let r=[Mi(Ms(),".config",e),Mi(Ms(),".config"),Ms()],n=[];for(let i of r)n.push(...this.fileLoader.generateConfigPaths(e,i,t));return n}async loadConfigWithResult(e){return this.loadConfig(e)}}var Vu=new Df;async function Of(e){let t="defaultConfig"in e&&e.defaultConfig!==void 0?e.defaultConfig:{},r="cache"in e||"performance"in e||"schema"in e||"validate"in e;try{let n;if(r)n=await Vu.loadConfig(e);else n=await Vu.loadConfig({...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}});return n?.config??t}catch(n){if(e.configFile)throw n;let i=n instanceof Error?n.name:"UnknownError",o=n instanceof Error?n.message:String(n);if(!(i==="ConfigNotFoundError"||i==="ConfigLoadError"||i==="ConfigValidationError"||o.includes("config"))&&e.verbose)fi.warn("Unexpected error loading config, using defaults:",[n instanceof Error?n:Error(String(n))]);let c=r?{...e,defaultConfig:t}:{...e,defaultConfig:t,cache:{enabled:!0},performance:{enabled:!1}};if("checkEnv"in e?e.checkEnv!==!1:!0)return(await Vu.applyEnvironmentVariables(c.name||"",t,!0,c.verbose||!1))?.config??t;return t}}function Ca(e,t,r=!1){let n=new ll,i=e.toUpperCase().replace(/[^A-Z0-9]/g,"_");function o(s,c=[]){let l={...s};for(let[a,m]of Object.entries(s)){let E=[...c,a],k=[`${i}_${E.join("_").toUpperCase()}`,`${i}_${E.map((G)=>G.toUpperCase()).join("")}`,`${i}_${E.map((G)=>G.replace(/([A-Z])/g,"_$1").toUpperCase()).join("")}`],O,q;for(let G of k)if(O=Kc.env[G],O!==void 0){q=G;break}if(O!==void 0&&q)if(typeof m==="boolean")l[a]=["true","1","yes"].includes(O.toLowerCase());else if(typeof m==="number"){let G=Number(O);if(!Number.isNaN(G))l[a]=G}else if(Array.isArray(m))try{l[a]=JSON.parse(O)}catch{l[a]=O.split(",").map((G)=>G.trim())}else l[a]=O;else if(m&&typeof m==="object"&&!Array.isArray(m))l[a]=o(m,E)}return l}return o(t)}var QD=Mi(Kc.cwd(),"config"),YD=Mi(Kc.cwd(),"src/generated");var ln={project:{name:"my-project",slug:"my-project",region:"us-east-1"},environments:{production:{type:"production"}}},cs=null;function VI(e){return e.project?.slug===ln.project?.slug&&Object.keys(e.environments??{}).length===1&&!!e.environments?.production}async function qI(){let e=[_f(process.cwd(),"config","cloud.ts"),_f(process.cwd(),"config","cloud.js")];for(let t of e){if(!UI(t))continue;let r=await import(`${zI(t).href}?t=${Date.now()}`),n=r.tsCloud??r.default?.tsCloud??r.default??r.cloud??r.config;if(n)return n}return null}async function JI(){if(!cs){if(cs=await Of({name:"cloud",defaultConfig:ln}),VI(cs))cs=await qI()??cs;Ds(cs.stateDir)}return cs}var Ei=JI;var WI=async(e)=>{let t=Bun.spawn(e,{stdout:"pipe",stderr:"pipe"}),[r,n,i]=await Promise.all([t.exited,new Response(t.stdout).text(),new Response(t.stderr).text()]);return{code:r,stdout:n,stderr:i}};class Ir{async scan(e,t){return Ji(e,t)}async exec(e,t){if(e.trustState!=="pinned")throw Error("SSH host key must be pinned before remote execution.");return WI(["ssh","-p",String(e.sshPort),"-o","BatchMode=yes","-o","StrictHostKeyChecking=yes","-o","ConnectTimeout=10",`${e.sshUser}@${e.endpoint}`,t])}}var HI=cr,GI=`set -eu; printf '{'; printf '"os":"%s",' "$(. /etc/os-release 2>/dev/null; printf %s "\${PRETTY_NAME:-Linux}")"; printf '"arch":"%s",' "$(uname -m)"; printf '"cpuCores":%s,' "$(getconf _NPROCESSORS_ONLN)"; printf '"memoryBytes":%s,' "$(awk '/MemTotal/{print $2*1024}' /proc/meminfo)"; printf '"diskBytes":%s,' "$(df -B1 / | awk 'NR==2{print $2}')"; printf '"diskFreeBytes":%s,' "$(df -B1 / | awk 'NR==2{print $4}')"; printf '"dnsOk":'; getent hosts example.com >/dev/null && printf true || printf false; printf ',"timeSkewSeconds":0,"tools":{"curl":"'; command -v curl >/dev/null && printf installed; printf '","tar":"'; command -v tar >/dev/null && printf installed; printf '"},"privilege":"'; sudo -n true >/dev/null 2>&1 && printf sudo || printf user; printf '"}'`;class Ye{provider;transport;discoverer;constructor(e,t=new Ir,r){this.provider=e;this.transport=t;this.discoverer=r}discover(e){return this.discoverer?.(e)??Promise.resolve([])}async test(e){try{let t=await this.transport.scan(e.endpoint,e.sshPort);return{reachable:!0,hostKeyAlgorithm:t.algorithm,hostKeyFingerprint:HI(t.key),latencyMs:0}}catch{return{reachable:!1,hostKeyAlgorithm:"unknown",hostKeyFingerprint:"",latencyMs:0}}}async validate(e){let t=await this.transport.exec(e,GI);if(t.code!==0)throw Error(`Fleet validation failed: ${t.stderr.trim()||t.code}`);try{return JSON.parse(t.stdout)}catch{throw Error("Fleet validation returned malformed facts.")}}async bootstrap(e,t){let r=await this.transport.exec(e,`sudo -n ts-cloud-agent bootstrap --version 1 --steps ${t.length}`);if(r.code!==0)throw Error(`Fleet bootstrap failed: ${r.stderr.trim()||r.code}`);return{version:"1"}}capabilities(){return{document:{supported:!0,reason:"fleet-capabilities/v1; sha256:driver-contract"},validate:{supported:!0},bootstrap:{supported:!0},heartbeat:{supported:!0},drain:{supported:!0},archive:{supported:!0},terminate:{supported:!1,reason:"Inventory removal never terminates provider infrastructure."}}}}function Nf(e,t){return{"fleet.bootstrap":async(r)=>{let n=r.operation.input&&typeof r.operation.input==="object"&&!Array.isArray(r.operation.input)?r.operation.input:{},i=e.get(String(n.serverId??""));if(!i)throw Error("Queued fleet server was not found.");let o=t.find((l)=>l.provider===i.provider);if(!o)throw Error(`No ${i.provider} fleet driver is configured.`);let s=Array.isArray(n.steps)?n.steps.map(String):[];if(r.checkpoint("preflight","Rechecking pinned trust and healthy validation."),i.trustState!=="pinned"||!i.validation?.valid)throw Error("Fleet bootstrap requires pinned trust and a healthy validation report.");r.checkpoint("bootstrap","Applying the reviewed idempotent bootstrap plan.");let c=await o.bootstrap(i,s);return e.update(i.id,{bootstrapVersion:c.version,status:"ready"}),r.checkpoint("verify","Bootstrap completed; heartbeat can now establish freshness."),{serverId:i.id,bootstrapVersion:c.version,steps:s.length}}}}var Li=(e)=>e==null?void 0:String(e),ds=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},pl=(e)=>({id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),resourceId:String(e.resource_id),name:String(e.name),provider:String(e.provider),providerId:Li(e.provider_id),region:Li(e.region),zone:Li(e.zone),endpoint:String(e.endpoint),sshUser:String(e.ssh_user),sshPort:Number(e.ssh_port),credentialRef:String(e.credential_ref),hostKeyAlgorithm:Li(e.host_key_algorithm),hostKeyFingerprint:Li(e.host_key_fingerprint),pendingHostKey:Li(e.pending_host_key),roles:ds(e.roles,[]),labels:ds(e.labels,{}),taints:ds(e.taints,[]),capacity:ds(e.capacity,{}),usage:ds(e.usage,{}),capabilities:ds(e.capabilities,{}),status:String(e.status),trustState:String(e.trust_state),validation:ds(e.validation,void 0),bootstrapVersion:Li(e.bootstrap_version),heartbeatAt:Li(e.heartbeat_at),lastSeenAt:Li(e.last_seen_at),archivedAt:Li(e.archived_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)});class Ae{control;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.control=e;this.now=t;this.id=r}get(e){let t=this.control.database.query("SELECT * FROM fleet_servers WHERE id=?").get(e);return t?pl(t):void 0}list(e,t=!1){return this.control.database.query("SELECT * FROM fleet_servers WHERE project_id=? ORDER BY name").all(e).map(pl).filter((r)=>t||r.status!=="archived")}findProvider(e,t,r){let n=this.control.database.query("SELECT * FROM fleet_servers WHERE organization_id=? AND provider=? AND provider_id=? AND archived_at IS NULL").get(e,t,r);return n?pl(n):void 0}create(e){let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO fleet_servers (id,organization_id,project_id,resource_id,name,provider,provider_id,region,zone,endpoint,ssh_user,ssh_port,credential_ref,host_key_algorithm,host_key_fingerprint,pending_host_key,roles,labels,taints,capacity,usage,capabilities,status,trust_state,validation,bootstrap_version,heartbeat_at,last_seen_at,archived_at,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.organizationId,e.projectId,e.resourceId,e.name,e.provider,e.providerId??null,e.region??null,e.zone??null,e.endpoint,e.sshUser,e.sshPort,e.credentialRef,e.hostKeyAlgorithm??null,e.hostKeyFingerprint??null,e.pendingHostKey??null,JSON.stringify(e.roles),JSON.stringify(e.labels),JSON.stringify(e.taints),JSON.stringify(e.capacity),JSON.stringify(e.usage),JSON.stringify(e.capabilities),e.status,e.trustState,JSON.stringify(e.validation??{}),e.bootstrapVersion??null,e.heartbeatAt??null,e.lastSeenAt??null,e.archivedAt??null,r,r]),this.get(t)}update(e,t){let r=this.get(e);if(!r)throw Error("Server was not found.");let n={...r,...t},i=this.now().toISOString();return this.control.database.run("UPDATE fleet_servers SET name=?,provider_id=?,region=?,zone=?,endpoint=?,ssh_user=?,ssh_port=?,credential_ref=?,host_key_algorithm=?,host_key_fingerprint=?,pending_host_key=?,roles=?,labels=?,taints=?,capacity=?,usage=?,capabilities=?,status=?,trust_state=?,validation=?,bootstrap_version=?,heartbeat_at=?,last_seen_at=?,archived_at=?,version=version+1,updated_at=? WHERE id=?",[n.name,n.providerId??null,n.region??null,n.zone??null,n.endpoint,n.sshUser,n.sshPort,n.credentialRef,n.hostKeyAlgorithm??null,n.hostKeyFingerprint??null,n.pendingHostKey??null,JSON.stringify(n.roles),JSON.stringify(n.labels),JSON.stringify(n.taints),JSON.stringify(n.capacity),JSON.stringify(n.usage),JSON.stringify(n.capabilities),n.status,n.trustState,JSON.stringify(n.validation??{}),n.bootstrapVersion??null,n.heartbeatAt??null,n.lastSeenAt??null,n.archivedAt??null,i,e]),this.get(e)}}var KI=/^(?:[A-Za-z0-9](?:[A-Za-z0-9.-]{0,251}[A-Za-z0-9])?|\[[0-9a-fA-F:]+\])$/;class un{store;drivers;now;queue;constructor(e,t,r,n=()=>new Date){this.store=e;this.drivers=t;this.now=n;this.queue=r??new b(e.control)}driver(e){let t=this.drivers.find((r)=>r.provider===e);if(!t)throw Error(`No ${e} fleet driver is configured.`);return t}enroll(e){if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(e.name))throw Error("Server name is invalid.");if(!KI.test(e.endpoint)||e.sshUser==="root"||!e.credentialRef.startsWith("secret://"))throw Error("Enrollment requires a valid endpoint, non-root SSH user, and secret credential reference.");let t=e.providerId?this.store.findProvider(e.organizationId,e.provider,e.providerId):void 0;if(t)return this.store.update(t.id,{endpoint:e.endpoint,region:e.region,zone:e.zone});let r=this.store.control.createResource({projectId:e.projectId,kind:"server",slug:e.name,name:e.name,provider:e.provider,providerId:e.providerId}),n=this.driver(e.provider);return this.store.create({...e,resourceId:r.id,sshPort:e.sshPort??22,labels:e.labels??{},taints:[],capacity:{},usage:{},capabilities:n.capabilities(),status:"pending",trustState:"unverified"})}async test(e){let t=this.store.get(e);if(!t)throw Error("Server was not found.");let r=await this.driver(t.provider).test(t);if(!r.reachable)return this.store.update(e,{status:"unreachable"});if(t.hostKeyFingerprint&&t.hostKeyFingerprint!==r.hostKeyFingerprint)return this.store.update(e,{status:"degraded",trustState:"rotation_pending",pendingHostKey:r.hostKeyFingerprint});return this.store.update(e,{hostKeyAlgorithm:r.hostKeyAlgorithm,hostKeyFingerprint:r.hostKeyFingerprint,pendingHostKey:void 0,trustState:"pinned",status:"validating",lastSeenAt:this.now().toISOString()})}reviewHostKey(e,t){let r=this.store.get(e);if(!r||r.pendingHostKey!==t)throw Error("Pending host key does not match.");return this.store.update(e,{hostKeyFingerprint:t,pendingHostKey:void 0,trustState:"pinned",status:"validating"})}async validate(e){let t=this.store.get(e);if(!t||t.trustState!=="pinned")throw Error("Pin the SSH host key before validation.");let r=await this.driver(t.provider).validate(t),n=[];if(!["x64","arm64","x86_64","aarch64"].includes(r.arch??""))n.push({code:"arch.unsupported",severity:"error",message:"Unsupported architecture.",remediation:"Use x86_64 or arm64 Linux."});for(let s of["curl","tar"])if(!r.tools?.[s])n.push({code:`tool.${s}`,severity:"error",message:`${s} is missing.`,remediation:`Install ${s} before bootstrap.`});if(Math.abs(r.timeSkewSeconds??0)>60)n.push({code:"time.skew",severity:"error",message:"Clock skew exceeds 60 seconds.",remediation:"Enable NTP synchronization."});if(!r.dnsOk)n.push({code:"dns.failed",severity:"error",message:"DNS validation failed.",remediation:"Repair resolver configuration."});let i={valid:!n.some((s)=>s.severity==="error"),facts:r,findings:n,validatedAt:this.now().toISOString(),validatorVersion:"1"},o={cpu:r.cpuCores??0,memoryBytes:r.memoryBytes??0,diskBytes:r.diskBytes??0};return this.store.update(e,{validation:i,capacity:o,status:i.valid?"ready":"degraded"})}bootstrap(e,t=!1){let r=this.store.get(e);if(!r?.validation?.valid)throw Error("A healthy validation report is required.");let n=["install runtime dependencies","install ts-cloud agent","configure heartbeat","verify least-privilege access"];if(!t)return{preview:!0,steps:n};let i=this.queue.enqueue({projectId:r.projectId,resourceId:r.resourceId,kind:"fleet.bootstrap",input:{serverId:e,steps:n},lockKey:`server:${e}`,providerKey:r.provider}).operation;return{preview:!1,steps:n,operation:i}}heartbeat(e,t){let r=this.store.get(e);if(!r)throw Error("Server was not found.");let n=this.now().toISOString();return this.store.update(e,{usage:t.usage,capabilities:t.capabilities??r.capabilities,heartbeatAt:n,lastSeenAt:n,status:r.status==="draining"||r.status==="drained"?r.status:"ready"})}drain(e,t=!1){return this.store.update(e,{status:t?"drained":"draining"})}uncordon(e){return this.store.update(e,{status:"ready"})}archive(e,t){let r=this.store.get(e);if(!r||t!==r.name)throw Error("Exact server name confirmation is required.");return this.store.update(e,{status:"archived",archivedAt:this.now().toISOString()})}}import{createHash as gl,createPublicKey as Lf,verify as QI}from"node:crypto";function xa(e){if(e===null||typeof e!=="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(xa).join(",")}]`;return`{${Object.keys(e).sort().map((t)=>`${JSON.stringify(t)}:${xa(e[t])}`).join(",")}}`}var Bf=(e)=>gl("sha256").update(xa(e)).digest("hex"),Zc=(e)=>gl("sha256").update(xa(e)).digest("hex"),jf=(e)=>gl("sha256").update(Lf(e).export({type:"spki",format:"der"})).digest("hex");function Ff(e,t,r){try{return QI(null,Buffer.from(xa(e)),Lf(r),Buffer.from(t,"base64"))}catch{return!1}}var $f=(e)=>e.replace(/^v/,"").split(/[.-]/).slice(0,3).map((t)=>Number(t)||0),Mf=(e,t)=>{let r=$f(e),n=$f(t);for(let i=0;i<3;i++){let o=(r[i]??0)-(n[i]??0);if(o)return o}return 0};function Uf(e,t){let r=[];if(t.schemaVersion<e.minimumSchema)r.push(`schema ${t.schemaVersion} is below ${e.minimumSchema}`);if(t.schemaVersion>e.maximumSchema)r.push(`schema ${t.schemaVersion} is above ${e.maximumSchema}`);if(e.minimumVersion&&Mf(t.currentVersion,e.minimumVersion)<0)r.push(`platform ${t.currentVersion} is below ${e.minimumVersion}`);if(Mf(e.version,t.currentVersion)<=0)r.push(`version ${e.version} is not newer than ${t.currentVersion}`);if(!e.artifacts.some((n)=>n.platform===t.platform&&n.architecture===t.architecture))r.push(`no artifact for ${t.platform}/${t.architecture}`);return{compatible:r.length===0,reasons:r}}var ro=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},qr=(e)=>e==null?void 0:String(e),YI=(e)=>({id:String(e.id),organizationId:String(e.organization_id),name:String(e.name),algorithm:"ed25519",publicKeyPem:String(e.public_key_pem),fingerprint:String(e.fingerprint),revokedAt:qr(e.revoked_at),createdAt:String(e.created_at)}),zf=(e)=>({id:String(e.id),organizationId:String(e.organization_id),version:String(e.version),channel:String(e.channel),publishedAt:String(e.published_at),keyId:String(e.key_id),digest:String(e.digest),document:ro(e.document,{}),signature:String(e.signature),verificationStatus:String(e.verification_status),compatibility:ro(e.compatibility,{compatible:!1,reasons:[]}),createdAt:String(e.created_at)}),Vf=(e)=>({id:String(e.id),projectId:String(e.project_id),name:String(e.name),schedule:String(e.schedule),timezone:String(e.timezone),durationMinutes:Number(e.duration_minutes),allowedOperations:ro(e.allowed_operations,[]),requireApproval:Number(e.require_approval)===1,enabled:Number(e.enabled)===1,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),qf=(e)=>({id:String(e.id),projectId:String(e.project_id),manifestId:String(e.manifest_id),windowId:qr(e.window_id),fromVersion:String(e.from_version),strategy:String(e.strategy),batchSize:Number(e.batch_size),healthGate:ro(e.health_gate,{}),status:String(e.status),currentStage:qr(e.current_stage),backupId:qr(e.backup_id),approvedBy:qr(e.approved_by),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),ml=(e)=>({id:String(e.id),campaignId:String(e.campaign_id),serverId:qr(e.server_id),target:String(e.target),cohort:Number(e.cohort),previousVersion:String(e.previous_version),status:String(e.status),evidence:ro(e.evidence,{}),error:qr(e.error),startedAt:qr(e.started_at),finishedAt:qr(e.finished_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),Jf=(e)=>({id:String(e.id),projectId:String(e.project_id),kind:String(e.kind),criteria:ro(e.criteria,{}),candidates:ro(e.candidates,[]),candidateDigest:String(e.candidate_digest),estimatedBytes:Number(e.estimated_bytes),status:String(e.status),confirmation:qr(e.confirmation),expiresAt:String(e.expires_at),result:ro(e.result,{}),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),Wf=(e)=>({id:String(e.id),projectId:String(e.project_id),backupPolicyId:qr(e.backup_policy_id),recoveryPointId:qr(e.recovery_point_id),topologyId:qr(e.topology_id),scenario:String(e.scenario),isolatedTarget:String(e.isolated_target),expectedRpoMinutes:Number(e.expected_rpo_minutes),expectedRtoMinutes:Number(e.expected_rto_minutes),status:String(e.status),operationId:qr(e.operation_id),evidence:ro(e.evidence,{}),measuredRpoMinutes:e.measured_rpo_minutes==null?void 0:Number(e.measured_rpo_minutes),measuredRtoMinutes:e.measured_rto_minutes==null?void 0:Number(e.measured_rto_minutes),cleanupVerified:Number(e.cleanup_verified)===1,error:qr(e.error),startedAt:qr(e.started_at),finishedAt:qr(e.finished_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)});class hn{control;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.control=e;this.now=t;this.id=r}addTrustedKey(e){let t=this.id(),r=this.now().toISOString(),n=jf(e.publicKeyPem);return this.control.database.run("INSERT INTO platform_trusted_keys (id,organization_id,name,algorithm,public_key_pem,fingerprint,created_at) VALUES (?,?,?,'ed25519',?,?,?)",[t,e.organizationId,e.name,e.publicKeyPem,n,r]),this.key(t)}key(e){let t=this.control.database.query("SELECT * FROM platform_trusted_keys WHERE id=?").get(e);return t?YI(t):void 0}revokeKey(e){return this.control.database.run("UPDATE platform_trusted_keys SET revoked_at=? WHERE id=?",[this.now().toISOString(),e]),this.key(e)}importManifest(e){let t=this.key(e.keyId);if(!t||t.organizationId!==e.organizationId)throw Error("Trusted update key was not found.");if(t.revokedAt)throw Error("Update signing key is revoked.");if(!Ff(e.document,e.signature,t.publicKeyPem))throw Error("Update manifest signature is invalid.");let r=Uf(e.document,e.current),n=Bf(e.document),i=this.id(),o=this.now().toISOString();return this.control.database.run("INSERT INTO platform_update_manifests (id,organization_id,version,channel,published_at,key_id,digest,document,signature,verification_status,compatibility,created_at) VALUES (?,?,?,?,?,?,?,?,?,'verified',?,?)",[i,e.organizationId,e.document.version,e.document.channel,new Date(e.document.publishedAt).toISOString(),e.keyId,n,JSON.stringify(e.document),e.signature,JSON.stringify(r),o]),this.manifest(i)}manifest(e){let t=this.control.database.query("SELECT * FROM platform_update_manifests WHERE id=?").get(e);return t?zf(t):void 0}manifests(e){return this.control.database.query("SELECT * FROM platform_update_manifests WHERE organization_id=? ORDER BY published_at DESC").all(e).map(zf)}createWindow(e){let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO maintenance_windows (id,project_id,name,schedule,timezone,duration_minutes,allowed_operations,require_approval,enabled,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,1,?,?)",[t,e.projectId,e.name,e.schedule,e.timezone,e.durationMinutes,JSON.stringify(e.allowedOperations),e.requireApproval===!1?0:1,r,r]),this.window(t)}window(e){let t=this.control.database.query("SELECT * FROM maintenance_windows WHERE id=?").get(e);return t?Vf(t):void 0}windows(e){return this.control.database.query("SELECT * FROM maintenance_windows WHERE project_id=? ORDER BY name").all(e).map(Vf)}createCampaign(e){return this.control.transaction(()=>{let t=this.manifest(e.manifestId);if(!t?.compatibility.compatible||t.verificationStatus!=="verified")throw Error("A verified compatible update manifest is required.");if(!e.backupId)throw Error("A verified pre-upgrade backup is required.");let r=this.id(),n=this.now().toISOString();return this.control.database.run("INSERT INTO platform_upgrade_campaigns (id,project_id,manifest_id,window_id,from_version,strategy,batch_size,health_gate,status,backup_id,approved_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?, 'planned',?,?,?,?)",[r,e.projectId,e.manifestId,e.windowId??null,e.fromVersion,e.strategy,e.batchSize,JSON.stringify(e.healthGate),e.backupId,e.approvedBy??null,n,n]),e.targets.forEach((i,o)=>this.control.database.run("INSERT INTO platform_upgrade_targets (id,campaign_id,server_id,target,cohort,previous_version,status,created_at,updated_at) VALUES (?,?,?,?,?,?,'pending',?,?)",[this.id(),r,i.serverId??null,i.target,e.strategy==="canary"?o===0?0:1+Math.floor((o-1)/e.batchSize):Math.floor(o/e.batchSize),i.previousVersion,n,n])),this.campaign(r)})}campaign(e){let t=this.control.database.query("SELECT * FROM platform_upgrade_campaigns WHERE id=?").get(e);return t?qf(t):void 0}campaigns(e){return this.control.database.query("SELECT * FROM platform_upgrade_campaigns WHERE project_id=? ORDER BY created_at DESC").all(e).map(qf)}targets(e){return this.control.database.query("SELECT * FROM platform_upgrade_targets WHERE campaign_id=? ORDER BY cohort,target").all(e).map(ml)}updateCampaign(e,t){let r=this.campaign(e);if(!r)throw Error("Upgrade campaign was not found.");let n={...r,...t};return this.control.database.run("UPDATE platform_upgrade_campaigns SET status=?,current_stage=?,updated_at=? WHERE id=?",[n.status,n.currentStage??null,this.now().toISOString(),e]),this.campaign(e)}updateTarget(e,t){let r=this.control.database.query("SELECT * FROM platform_upgrade_targets WHERE id=?").get(e);if(!r)throw Error("Upgrade target was not found.");let n={...ml(r),...t};return this.control.database.run("UPDATE platform_upgrade_targets SET status=?,evidence=?,error=?,started_at=?,finished_at=?,updated_at=? WHERE id=?",[n.status,JSON.stringify(n.evidence),n.error??null,n.startedAt??null,n.finishedAt??null,this.now().toISOString(),e]),ml(this.control.database.query("SELECT * FROM platform_upgrade_targets WHERE id=?").get(e))}createCleanup(e){let t=[...e.candidates].sort((s,c)=>s.id.localeCompare(c.id)),r=Zc(t),n=this.id(),i=this.now().toISOString(),o=new Date(this.now().getTime()+(e.ttlMinutes??60)*60000).toISOString();return this.control.database.run("INSERT INTO cleanup_plans (id,project_id,kind,criteria,candidates,candidate_digest,estimated_bytes,status,expires_at,created_at,updated_at) VALUES (?,?,?,?,?,?,?,'preview',?,?,?)",[n,e.projectId,e.kind,JSON.stringify(e.criteria),JSON.stringify(t),r,t.reduce((s,c)=>s+c.bytes,0),o,i,i]),this.cleanup(n)}cleanup(e){let t=this.control.database.query("SELECT * FROM cleanup_plans WHERE id=?").get(e);return t?Jf(t):void 0}cleanups(e){return this.control.database.query("SELECT * FROM cleanup_plans WHERE project_id=? ORDER BY created_at DESC").all(e).map(Jf)}updateCleanup(e,t){let r=this.cleanup(e);if(!r)throw Error("Cleanup plan was not found.");let n={...r,...t};return this.control.database.run("UPDATE cleanup_plans SET status=?,confirmation=?,result=?,updated_at=? WHERE id=?",[n.status,n.confirmation??null,JSON.stringify(n.result),this.now().toISOString(),e]),this.cleanup(e)}createDrill(e){if(!/^isolated:\/\//.test(e.isolatedTarget))throw Error("DR drills require an isolated target.");let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO disaster_recovery_drills (id,project_id,backup_policy_id,recovery_point_id,topology_id,scenario,isolated_target,expected_rpo_minutes,expected_rto_minutes,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,'planned',?,?)",[t,e.projectId,e.backupPolicyId??null,e.recoveryPointId??null,e.topologyId??null,e.scenario,e.isolatedTarget,e.expectedRpoMinutes,e.expectedRtoMinutes,r,r]),this.drill(t)}drill(e){let t=this.control.database.query("SELECT * FROM disaster_recovery_drills WHERE id=?").get(e);return t?Wf(t):void 0}drills(e){return this.control.database.query("SELECT * FROM disaster_recovery_drills WHERE project_id=? ORDER BY created_at DESC").all(e).map(Wf)}updateDrill(e,t){let r=this.drill(e);if(!r)throw Error("DR drill was not found.");let n={...r,...t};return this.control.database.run("UPDATE disaster_recovery_drills SET status=?,operation_id=?,evidence=?,measured_rpo_minutes=?,measured_rto_minutes=?,cleanup_verified=?,error=?,started_at=?,finished_at=?,updated_at=? WHERE id=?",[n.status,n.operationId??null,JSON.stringify(n.evidence),n.measuredRpoMinutes??null,n.measuredRtoMinutes??null,n.cleanupVerified?1:0,n.error??null,n.startedAt??null,n.finishedAt??null,this.now().toISOString(),e]),this.drill(e)}}function XI(e,t=new Date){if(!e.enabled)return!1;let r=new Date(e.schedule);if(!Number.isNaN(r.getTime()))return t>=r&&t.getTime()<=r.getTime()+e.durationMinutes*60000;let n=/^(\d{2}):(\d{2})$/.exec(e.schedule);if(!n)return!1;let i=new Intl.DateTimeFormat("en-US",{timeZone:e.timezone,hour:"2-digit",minute:"2-digit",hourCycle:"h23"}).formatToParts(t),o=Number(i.find((c)=>c.type==="hour")?.value)*60+Number(i.find((c)=>c.type==="minute")?.value),s=Number(n[1])*60+Number(n[2]);return o>=s&&o<s+e.durationMinutes}class yn{store;now;queue;constructor(e,t,r=()=>new Date){this.store=e;this.now=r;this.queue=t??new b(e.control)}enqueueCampaign(e,t={}){let r=this.store.campaign(e);if(!r)throw Error("Upgrade campaign was not found.");let n=r.windowId?this.store.window(r.windowId):void 0;if(n&&!n.allowedOperations.includes("platform.upgrade"))throw Error("Maintenance window does not permit platform upgrades.");if(n&&!t.overrideWindow&&!XI(n,this.now()))throw Error("Upgrade is outside its maintenance window.");if(n?.requireApproval&&!t.approvedBy&&!r.approvedBy)throw Error("Maintenance approval is required.");let i=this.queue.enqueue({projectId:r.projectId,actorId:t.approvedBy,kind:"maintenance.upgrade",input:{campaignId:e},lockKey:"platform-upgrade",providerKey:"platform",timeoutSeconds:7200,cancellationMode:"cooperative",resumePolicy:"fail"}).operation;return{campaign:this.store.updateCampaign(e,{status:"queued"}),operation:i}}async previewCleanup(e,t){let r=t.find((n)=>n.kind===e.kind);if(!r)throw Error(`No ${e.kind} cleanup driver is configured.`);return this.store.createCleanup({...e,candidates:await r.discover(e.criteria)})}enqueueCleanup(e,t){let r=this.store.cleanup(e);if(!r||r.status!=="preview")throw Error("A current cleanup preview is required.");if(new Date(r.expiresAt)<=this.now())throw Error("Cleanup preview expired; generate it again.");let n=`DELETE ${r.candidates.length} ${r.kind}`;if(t!==n)throw Error(`Exact confirmation ${n} is required.`);let i=this.queue.enqueue({projectId:r.projectId,kind:"maintenance.cleanup",input:{planId:e},lockKey:`cleanup:${r.kind}`,providerKey:"cleanup",timeoutSeconds:3600,cancellationMode:"cooperative"}).operation;return{plan:this.store.updateCleanup(e,{status:"approved",confirmation:t}),operation:i}}enqueueDrill(e){let t=this.store.drill(e);if(!t||t.status!=="planned")throw Error("A planned DR drill is required.");let r=this.queue.enqueue({projectId:t.projectId,kind:"maintenance.drill",input:{drillId:e},lockKey:`drill:${t.scenario}:${t.id}`,providerKey:"recovery",timeoutSeconds:7200,cancellationMode:"cooperative"}).operation;return{drill:this.store.updateDrill(e,{status:"queued",operationId:r.id}),operation:r}}}var fl=(e)=>e&&typeof e==="object"&&!Array.isArray(e)?e:{};function Hf(e){return{"maintenance.upgrade":async(i)=>{let o=e.store.campaign(String(fl(i.operation.input).campaignId??""));if(!o||!e.platform)throw Error("Upgrade campaign or platform maintenance driver is unavailable.");let s=e.store.manifest(o.manifestId);if(!s?.compatibility.compatible||s.verificationStatus!=="verified")throw Error("Update manifest is no longer verified and compatible.");let c=s.document.artifacts.find((a)=>a.platform===process.platform&&a.architecture===process.arch)??s.document.artifacts[0];if(!c)throw Error("No update artifact matches this platform.");e.store.updateCampaign(o.id,{status:"running",currentStage:"preflight"});let l=[];try{for(let a of[...new Set(e.store.targets(o.id).map((m)=>m.cohort))].sort((m,E)=>m-E)){e.store.updateCampaign(o.id,{currentStage:`cohort:${a}`});for(let m of e.store.targets(o.id).filter((E)=>E.cohort===a)){i.throwIfCancellationRequested(),i.checkpoint(`download:${m.target}`,"Downloading signed platform artifact."),e.store.updateTarget(m.id,{status:"downloading",startedAt:new Date().toISOString()});let E=await e.platform.download({target:m,artifact:c,signal:i.signal});if(E.sha256!==c.sha256)throw Error(`Artifact checksum mismatch for ${m.target}.`);i.checkpoint(`install:${m.target}`,"Installing verified artifact."),e.store.updateTarget(m.id,{status:"installing"}),await e.platform.install({target:m,path:E.path,version:s.version,signal:i.signal}),l.push(m);let k=await e.platform.health({target:m,gate:o.healthGate});if(!k.healthy)throw Error(`Upgrade health gate failed for ${m.target}.`);e.store.updateTarget(m.id,{status:"healthy",evidence:k.evidence,finishedAt:new Date().toISOString()})}}return e.store.updateCampaign(o.id,{status:"succeeded",currentStage:void 0}),{campaignId:o.id,version:s.version,targets:l.length}}catch(a){e.store.updateCampaign(o.id,{status:"rolling_back",currentStage:"rollback"});for(let m of l.reverse())e.store.updateTarget(m.id,{status:"rolling_back"}),await e.platform.rollback({target:m,version:m.previousVersion,signal:i.signal}),e.store.updateTarget(m.id,{status:"rolled_back",finishedAt:new Date().toISOString()});throw e.store.updateCampaign(o.id,{status:"rolled_back",currentStage:void 0}),a}},"maintenance.cleanup":async(i)=>{let o=e.store.cleanup(String(fl(i.operation.input).planId??""));if(!o||o.status!=="approved")throw Error("Approved cleanup plan was not found.");if(Zc([...o.candidates].sort((m,E)=>m.id.localeCompare(E.id)))!==o.candidateDigest)throw Error("Cleanup candidate set changed after preview.");let s=e.cleanup?.find((m)=>m.kind===o.kind);if(!s)throw Error(`No ${o.kind} cleanup driver is configured.`);e.store.updateCleanup(o.id,{status:"running"});let c=[],l=[];for(let m of o.candidates){i.throwIfCancellationRequested();try{await s.remove(m),c.push(m.id)}catch(E){l.push({id:m.id,error:E instanceof Error?E.message:String(E)})}}let a=l.length?c.length?"partial":"failed":"succeeded";if(e.store.updateCleanup(o.id,{status:a,result:{removed:c,failed:l,reclaimedBytes:o.candidates.filter((m)=>c.includes(m.id)).reduce((m,E)=>m+E.bytes,0)}}),l.length)throw Error(`Cleanup failed for ${l.length} candidate(s).`);return{planId:o.id,removed:c.length,reclaimedBytes:o.estimatedBytes}},"maintenance.drill":async(i)=>{let o=e.store.drill(String(fl(i.operation.input).drillId??""));if(!o)throw Error("DR drill was not found.");let s=e.recovery?.find((E)=>E.scenario===o.scenario);if(!s)throw Error(`No ${o.scenario} recovery driver is configured.`);let c=new Date;e.store.updateDrill(o.id,{status:"restoring",startedAt:c.toISOString()});let l=o.isolatedTarget,a={},m={};try{i.checkpoint("restore","Restoring into isolated drill target.");let E=await s.restore({drill:o,signal:i.signal});if(!E.target.startsWith("isolated://"))throw Error("Recovery driver attempted a non-isolated target.");l=E.target,a=E.evidence;let k=(c.getTime()-new Date(E.recoveryPointAt).getTime())/60000;e.store.updateDrill(o.id,{status:"verifying",measuredRpoMinutes:k,evidence:{restore:a}}),i.checkpoint("verify","Running recovery health checks without production traffic.");let O=await s.verify({drill:o,target:l});m=O.evidence;let q=(Date.now()-c.getTime())/60000;if(!O.healthy||k>o.expectedRpoMinutes||q>o.expectedRtoMinutes)throw Error("DR drill failed its health, RPO, or RTO objective.");e.store.updateDrill(o.id,{measuredRpoMinutes:k,measuredRtoMinutes:q,evidence:{restore:a,verify:m}})}catch(E){throw e.store.updateDrill(o.id,{status:"failed",error:E instanceof Error?E.message:String(E),evidence:{restore:a,verify:m}}),E}finally{e.store.updateDrill(o.id,{status:"cleaning"});try{await s.cleanup({drill:o,target:l});let E=e.store.drill(o.id);e.store.updateDrill(o.id,{status:E.error?"failed":"passed",cleanupVerified:!0,finishedAt:new Date().toISOString()})}catch(E){e.store.updateDrill(o.id,{status:"cleanup_required",cleanupVerified:!1,error:E instanceof Error?E.message:String(E),finishedAt:new Date().toISOString()})}}return{drillId:o.id,status:e.store.drill(o.id).status}}}}var Gf={releases:{select:"SELECT id,created_at,0 bytes FROM releases WHERE project_id=? AND pinned=0 AND status IN ('failed','rolled_back','superseded') AND created_at<?",remove:"DELETE FROM releases WHERE id=?"},artifacts:{select:"SELECT a.id,a.created_at,a.size bytes FROM release_artifacts a WHERE a.organization_id=? AND NOT EXISTS(SELECT 1 FROM releases r WHERE r.artifact_id=a.id) AND a.created_at<?",remove:"DELETE FROM release_artifacts WHERE id=?"},operations:{select:"SELECT id,created_at,0 bytes FROM operations WHERE project_id=? AND state IN ('succeeded','failed','cancelled','timed_out') AND updated_at<?",remove:"DELETE FROM operations WHERE id=?"},logs:{select:"SELECT l.id,l.created_at,length(l.message) bytes FROM operation_logs l JOIN operations o ON o.id=l.operation_id WHERE o.project_id=? AND o.state IN ('succeeded','failed','cancelled','timed_out') AND l.created_at<?",remove:"DELETE FROM operation_logs WHERE id=?"},previews:{select:"SELECT id,created_at,0 bytes FROM preview_instances WHERE project_id=? AND status IN ('destroyed','failed') AND updated_at<?",remove:"DELETE FROM preview_instances WHERE id=?"},snapshots:{select:"SELECT id,created_at,size_bytes bytes FROM recovery_points WHERE project_id=? AND pinned=0 AND held=0 AND status IN ('failed','deleted') AND created_at<?",remove:"DELETE FROM recovery_points WHERE id=?"},orphaned_resources:{select:"SELECT id,created_at,COALESCE(capacity_bytes,0) bytes FROM persistent_volumes WHERE project_id=? AND status='orphaned' AND orphaned_at<?",remove:"UPDATE persistent_volumes SET status='deleted',deleted_at=datetime('now'),updated_at=datetime('now') WHERE id=? AND status='orphaned'"}};class Sn{kind;control;projectId;organizationId;constructor(e,t,r,n){this.kind=e;this.control=t;this.projectId=r;this.organizationId=n}async discover(e){let t=Math.max(1,Math.min(3650,Number(e.olderThanDays??30))),r=new Date(Date.now()-t*86400000).toISOString(),n=Gf[this.kind],i=this.kind==="artifacts"?this.organizationId:this.projectId;return this.control.database.query(n.select).all(i,r).map((s)=>({id:String(s.id),kind:this.kind,label:`${this.kind}:${String(s.id)}`,bytes:Number(s.bytes??0),metadata:{createdAt:String(s.created_at)}}))}async remove(e){if(this.control.database.run(Gf[this.kind].remove,[e.id]).changes!==1)throw Error(`${e.label} changed or is no longer removable.`)}}var bi=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},Kn=(e)=>e==null?void 0:String(e),Yf=()=>({cpu:0,memoryBytes:0,diskBytes:0,gpu:0}),Gs=(e={})=>({...Yf(),...e});function Kf(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),name:String(e.name),purpose:String(e.purpose),backend:String(e.backend),region:Kn(e.region),architecture:Kn(e.architecture),labels:bi(e.labels,{}),requiredServerLabels:bi(e.required_server_labels,{}),toleratedTaints:bi(e.tolerated_taints,[]),capacity:Gs(bi(e.capacity,{})),reserved:bi(e.reserved,{}),maxWorkloads:Number(e.max_workloads),costWeight:Number(e.cost_weight),spreadKey:Kn(e.spread_key),concurrency:Number(e.concurrency),ephemeralWorkspaces:Number(e.ephemeral_workspaces)===1,allowProductionSecrets:Number(e.allow_production_secrets)===1,status:String(e.status),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Qf(e){return{id:String(e.id),projectId:String(e.project_id),environmentId:Kn(e.environment_id),resourceId:String(e.resource_id),releaseId:Kn(e.release_id),poolId:String(e.pool_id),serverId:Kn(e.server_id),purpose:String(e.purpose),requirements:bi(e.requirements,{}),decision:bi(e.decision,{}),stateful:Number(e.stateful)===1,autoReschedule:Number(e.auto_reschedule)===1,status:String(e.status),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ZI(e){return{id:String(e.id),projectId:String(e.project_id),resourceId:Kn(e.resource_id),poolId:String(e.pool_id),placementId:Kn(e.placement_id),operationId:Kn(e.operation_id),sourceSha:String(e.source_sha),buildSpec:bi(e.build_spec,{}),credentialPolicy:bi(e.credential_policy,{productionSecrets:!1,shortLivedTokenExpiresAt:""}),workspace:Kn(e.workspace),cacheKey:Kn(e.cache_key),artifactUri:Kn(e.artifact_uri),artifactDigest:Kn(e.artifact_digest),status:String(e.status),cleanupAt:Kn(e.cleanup_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}class pn{control;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.control=e;this.now=t;this.id=r}createPool(e){let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO capacity_pools (id,organization_id,project_id,name,purpose,backend,region,architecture,labels,required_server_labels,tolerated_taints,capacity,reserved,max_workloads,cost_weight,spread_key,concurrency,ephemeral_workspaces,allow_production_secrets,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.organizationId,e.projectId,e.name,e.purpose,e.backend,e.region??null,e.architecture??null,JSON.stringify(e.labels),JSON.stringify(e.requiredServerLabels),JSON.stringify(e.toleratedTaints),JSON.stringify(Gs(e.capacity)),"{}",e.maxWorkloads,e.costWeight,e.spreadKey??null,e.concurrency,e.ephemeralWorkspaces?1:0,e.allowProductionSecrets?1:0,e.status,r,r]),this.getPool(t)}getPool(e){let t=this.control.database.query("SELECT * FROM capacity_pools WHERE id=?").get(e);return t?Kf(t):void 0}listPools(e){return this.control.database.query("SELECT * FROM capacity_pools WHERE project_id=? ORDER BY name").all(e).map(Kf)}updatePool(e,t){let r=this.getPool(e);if(!r)throw Error("Capacity pool was not found.");let n={...r,...t},i=this.now().toISOString();return this.control.database.run("UPDATE capacity_pools SET status=?,reserved=?,capacity=?,concurrency=?,version=version+1,updated_at=? WHERE id=?",[n.status,JSON.stringify(n.reserved),JSON.stringify(n.capacity),n.concurrency,i,e]),this.getPool(e)}addMember(e,t,r={}){let n=this.now().toISOString();this.control.database.run("INSERT INTO capacity_pool_members (pool_id,server_id,capacity_override,status,created_at,updated_at) VALUES (?,?,?,'active',?,?) ON CONFLICT(pool_id,server_id) DO UPDATE SET capacity_override=excluded.capacity_override,status='active',updated_at=excluded.updated_at",[e,t,JSON.stringify(r),n,n])}members(e){return this.control.database.query("SELECT * FROM capacity_pool_members WHERE pool_id=? ORDER BY server_id").all(e).map((t)=>({serverId:String(t.server_id),status:String(t.status),capacityOverride:bi(t.capacity_override,{})}))}memberStatus(e,t,r){this.control.database.run("UPDATE capacity_pool_members SET status=?,updated_at=? WHERE pool_id=? AND server_id=?",[r,this.now().toISOString(),e,t])}listPlacements(e,t){let r=this.control.database.query("SELECT * FROM workload_placements WHERE project_id=? ORDER BY created_at,id").all(e).map(Qf);return t?.length?r.filter((n)=>t.includes(n.status)):r}getPlacement(e){let t=this.control.database.query("SELECT * FROM workload_placements WHERE id=?").get(e);return t?Qf(t):void 0}activeUsage(e,t){let r=this.control.database.query("SELECT l.resources,l.server_id FROM capacity_leases l WHERE l.pool_id=? AND l.state='active' AND l.expires_at>?").all(e,this.now().toISOString()),n=t?r.filter((i)=>String(i.server_id)===t):r;return{resources:n.reduce((i,o)=>{let s=Gs(bi(o.resources,{}));for(let c of Object.keys(i))i[c]+=s[c];return i},Yf()),count:n.length}}expireLeases(){return this.control.database.run("UPDATE capacity_leases SET state='expired',updated_at=? WHERE state='active' AND expires_at<=?",[this.now().toISOString(),this.now().toISOString()]).changes}reserve(e){return this.control.transaction(()=>{this.expireLeases();let t=this.id(),r=this.id(),n=this.now().toISOString(),i=new Date(this.now().getTime()+(e.requirements.leaseSeconds??300)*1000).toISOString();return this.control.database.run("INSERT INTO workload_placements (id,project_id,environment_id,resource_id,release_id,pool_id,server_id,purpose,requirements,decision,stateful,auto_reschedule,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,'reserved',?,?)",[t,e.projectId,e.environmentId??null,e.resourceId,e.releaseId??null,e.decision.poolId,e.decision.serverId??null,e.requirements.purpose,JSON.stringify(e.requirements),JSON.stringify(e.decision),e.requirements.stateful?1:0,e.requirements.autoReschedule&&!e.requirements.stateful?1:0,n,n]),this.control.database.run("INSERT INTO capacity_leases (id,placement_id,pool_id,server_id,resources,state,expires_at,created_at,updated_at) VALUES (?,?,?,?,?,'active',?,?,?)",[r,t,e.decision.poolId,e.decision.serverId??null,JSON.stringify(Gs(e.requirements.resources)),i,n,n]),this.getPlacement(t)})}transitionPlacement(e,t){if(!this.getPlacement(e))throw Error("Placement was not found.");let n=this.now().toISOString();if(this.control.database.run("UPDATE workload_placements SET status=?,version=version+1,updated_at=? WHERE id=?",[t,n,e]),["released","failed","blocked"].includes(t))this.control.database.run("UPDATE capacity_leases SET state='released',updated_at=? WHERE placement_id=? AND state='active'",[n,e]);return this.getPlacement(e)}createBuild(e){let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO remote_builds (id,project_id,resource_id,pool_id,placement_id,operation_id,source_sha,build_spec,credential_policy,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,'queued',?,?)",[t,e.projectId,e.resourceId??null,e.poolId,e.placementId??null,e.operationId??null,e.sourceSha,JSON.stringify(e.buildSpec),JSON.stringify({productionSecrets:!1,shortLivedTokenExpiresAt:e.tokenExpiresAt}),r,r]),this.getBuild(t)}getBuild(e){let t=this.control.database.query("SELECT * FROM remote_builds WHERE id=?").get(e);return t?ZI(t):void 0}updateBuild(e,t){let r=this.getBuild(e);if(!r)throw Error("Remote build was not found.");let n={...r,...t},i=this.now().toISOString();return this.control.database.run("UPDATE remote_builds SET operation_id=?,workspace=?,cache_key=?,artifact_uri=?,artifact_digest=?,status=?,cleanup_at=?,updated_at=? WHERE id=?",[n.operationId??null,n.workspace??null,n.cacheKey??null,n.artifactUri??null,n.artifactDigest??null,n.status,n.cleanupAt??null,i,e]),this.getBuild(e)}}var ed=["cpu","memoryBytes","diskBytes","gpu"],Xf=(e,t={})=>Object.entries(t).every(([r,n])=>e[r]===n),eC=(e,t,r)=>Object.fromEntries(ed.map((n)=>[n,Math.max(0,e[n]-t[n]-(r[n]??0))])),tC=(e,t)=>ed.every((r)=>e[r]>=(t[r]??0)),rC=(e,t)=>ed.reduce((r,n)=>r+(t[n]??0)/(e[n]||1),0);class mn{store;fleet;constructor(e,t){this.store=e;this.fleet=t}poolCandidates(e,t,r){let n=[];for(let i of this.store.listPools(e)){if(i.id===r)continue;let o=[];if(i.status!=="active")o.push(`pool is ${i.status}`);if(i.purpose!==t.purpose)o.push(`purpose is ${i.purpose}`);if(t.region&&i.region!==t.region)o.push(`region is ${i.region??"unset"}`);if(t.architecture&&i.architecture!==t.architecture)o.push(`architecture is ${i.architecture??"unset"}`);if(!Xf(i.labels,t.labels))o.push("pool labels do not match");if(i.backend==="server"){let s=this.store.members(i.id);if(!s.length)n.push(this.decision(i,void 0,t,[...o,"pool has no servers"]));for(let c of s){let l=this.fleet.get(c.serverId),a=[...o];if(!l)a.push("server is missing");else this.serverReasons(i,l,c.status,t,a);n.push(this.decision(i,l,t,a,c.capacityOverride))}}else n.push(this.decision(i,void 0,t,o))}return n.sort((i,o)=>Number(o.eligible)-Number(i.eligible)||i.score.cost-o.score.cost||i.score.spread-o.score.spread||i.score.fit-o.score.fit||i.poolName.localeCompare(o.poolName)||(i.serverId??"").localeCompare(o.serverId??""))}serverReasons(e,t,r,n,i){if(r!=="active")i.push(`member is ${r}`);if(t.status!=="ready")i.push(`server is ${t.status}`);if(!t.roles.includes(n.purpose==="build"?"build":n.purpose))i.push(`server lacks ${n.purpose} role`);if(!Xf(t.labels,e.requiredServerLabels))i.push("server labels do not match pool selector");for(let o of t.taints)if(!e.toleratedTaints.includes(o))i.push(`taint ${o} is not tolerated`)}decision(e,t,r,n,i={}){let o=Gs({...t?.capacity,...i}),s=t?Object.fromEntries(ed.map((a)=>[a,Math.min(e.capacity[a],o[a])])):e.capacity,c=this.store.activeUsage(e.id,t?.id),l=eC(s,c.resources,e.reserved);if(c.count>=e.maxWorkloads)n.push("workload limit reached");if(r.purpose==="build"&&c.count>=e.concurrency)n.push("build concurrency reached");if(!tC(l,r.resources))n.push("insufficient capacity");return{poolId:e.id,poolName:e.name,serverId:t?.id,eligible:n.length===0,reasons:n,available:l,score:{fit:rC(l,r.resources),spread:c.count,cost:e.costWeight}}}explain(e,t){return this.poolCandidates(e,t)}place(e){return this.store.control.transaction(()=>{let t=this.poolCandidates(e.projectId,e.requirements).find((r)=>r.eligible);if(!t)throw Error(`No eligible capacity: ${this.explain(e.projectId,e.requirements).flatMap((r)=>r.reasons).join("; ")}`);return this.store.reserve({...e,decision:t})})}activate(e){return this.store.transitionPlacement(e,"active")}release(e){return this.store.transitionPlacement(e,"released")}drainPool(e){let t=this.store.updatePool(e,{status:"draining"}),r=[],n=[];for(let i of this.store.listPlacements(t.projectId,["reserved","active"]).filter((o)=>o.poolId===e)){if(i.stateful){n.push(this.store.transitionPlacement(i.id,"blocked"));continue}this.store.transitionPlacement(i.id,"moving");let o=this.place({projectId:i.projectId,environmentId:i.environmentId,resourceId:i.resourceId,releaseId:i.releaseId,requirements:i.requirements});r.push(this.activate(o.id)),this.store.transitionPlacement(i.id,"released")}return{pool:t,moved:r,blocked:n}}drainServer(e,t){this.store.memberStatus(e,t,"draining");let r=this.store.getPool(e);if(!r)throw Error("Capacity pool was not found.");let n=[],i=[];for(let o of this.store.listPlacements(r.projectId,["reserved","active"]).filter((s)=>s.poolId===e&&s.serverId===t)){if(o.stateful){i.push(this.store.transitionPlacement(o.id,"blocked"));continue}this.store.transitionPlacement(o.id,"moving");let s=this.poolCandidates(o.projectId,o.requirements).find((l)=>l.eligible);if(!s){i.push(this.store.transitionPlacement(o.id,"blocked"));continue}let c=this.store.reserve({projectId:o.projectId,environmentId:o.environmentId,resourceId:o.resourceId,releaseId:o.releaseId,requirements:o.requirements,decision:s});n.push(this.activate(c.id)),this.store.transitionPlacement(o.id,"released")}return{moved:n,blocked:i}}reconcileFailure(e){let t=this.fleet.get(e);if(!t)throw Error("Server was not found.");let r=[],n=[];for(let i of this.store.listPlacements(t.projectId,["active"]).filter((o)=>o.serverId===e)){if(i.stateful||!i.autoReschedule){n.push(this.store.transitionPlacement(i.id,"blocked"));continue}this.store.transitionPlacement(i.id,"failed");let o=this.place({projectId:i.projectId,environmentId:i.environmentId,resourceId:i.resourceId,releaseId:i.releaseId,requirements:i.requirements});r.push(this.activate(o.id))}return{rescheduled:r,blocked:n}}}var io=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},ui=(e)=>e==null?void 0:String(e),Zf=(e)=>({id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:ui(e.environment_id),name:String(e.name),hostname:String(e.hostname),homeRegion:String(e.home_region),regions:io(e.regions,[]),trafficPolicy:String(e.traffic_policy),dataPolicy:io(e.data_policy,{replicate:[],maxLagSeconds:60,retainOnDestroy:!0}),status:String(e.status),activeRegion:String(e.active_region),revision:ui(e.revision),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),hl=(e)=>({id:String(e.id),topologyId:String(e.topology_id),region:String(e.region),role:String(e.role),provider:String(e.provider),stackId:ui(e.stack_id),stackRevision:ui(e.stack_revision),status:String(e.status),health:io(e.health,{}),lastHealthyAt:ui(e.last_healthy_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),yl=(e)=>({id:String(e.id),topologyId:String(e.topology_id),kind:String(e.kind),sourceRegion:String(e.source_region),targetRegion:String(e.target_region),config:io(e.config,{}),status:String(e.status),checkpoint:ui(e.checkpoint),lagSeconds:e.lag_seconds==null?void 0:Number(e.lag_seconds),lastVerifiedAt:ui(e.last_verified_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),bl=(e)=>({id:String(e.id),topologyId:String(e.topology_id),hostname:String(e.hostname),dnsProvider:String(e.dns_provider),cdnEnabled:Number(e.cdn_enabled)===1,wafEnabled:Number(e.waf_enabled)===1,weights:io(e.weights,{}),desiredWeights:io(e.desired_weights,{}),status:String(e.status),providerState:io(e.provider_state,{}),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}),eh=(e)=>({id:String(e.id),topologyId:String(e.topology_id),operationId:ui(e.operation_id),kind:String(e.kind),requestedRegion:ui(e.requested_region),revision:ui(e.revision),plan:io(e.plan,[]),currentStep:ui(e.current_step),completedSteps:io(e.completed_steps,[]),status:String(e.status),error:ui(e.error),createdAt:String(e.created_at),updatedAt:String(e.updated_at)});class gn{control;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.control=e;this.now=t;this.id=r}create(e){return this.control.transaction(()=>{if(e.regions.length<2||new Set(e.regions.map((o)=>o.region)).size!==e.regions.length||e.regions.filter((o)=>o.role==="primary").length!==1)throw Error("A topology requires unique regions and exactly one primary.");let t=e.regions.find((o)=>o.role==="primary"),r=this.id(),n=this.now().toISOString();this.control.database.run("INSERT INTO regional_topologies (id,organization_id,project_id,environment_id,name,hostname,home_region,regions,traffic_policy,data_policy,status,active_region,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,'draft',?,?,?)",[r,e.organizationId,e.projectId,e.environmentId??null,e.name,e.hostname,t.region,JSON.stringify(e.regions),e.trafficPolicy,JSON.stringify(e.dataPolicy),t.region,n,n]);for(let o of e.regions)this.control.database.run("INSERT INTO regional_targets (id,topology_id,region,role,provider,status,created_at,updated_at) VALUES (?,?,?,?,?,'pending',?,?)",[this.id(),r,o.region,o.role,o.provider,n,n]);for(let o of e.dataPolicy.replicate)for(let s of e.regions)for(let c of e.regions.filter((l)=>l.region!==s.region))this.control.database.run("INSERT INTO regional_replication_channels (id,topology_id,kind,source_region,target_region,config,status,created_at,updated_at) VALUES (?,?,?,?,?,?,'pending',?,?)",[this.id(),r,o,s.region,c.region,"{}",n,n]);let i=Object.fromEntries(e.regions.map((o)=>[o.region,o.region===t.region?100:0]));return this.control.database.run("INSERT INTO regional_traffic_routes (id,topology_id,hostname,dns_provider,cdn_enabled,waf_enabled,weights,desired_weights,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?, 'pending',?,?)",[this.id(),r,e.hostname,e.dnsProvider??"route53",e.cdnEnabled?1:0,e.wafEnabled?1:0,JSON.stringify(i),JSON.stringify(i),n,n]),this.get(r)})}get(e){let t=this.control.database.query("SELECT * FROM regional_topologies WHERE id=?").get(e);return t?Zf(t):void 0}list(e){return this.control.database.query("SELECT * FROM regional_topologies WHERE project_id=? ORDER BY name").all(e).map(Zf)}targets(e){return this.control.database.query("SELECT * FROM regional_targets WHERE topology_id=? ORDER BY role,region").all(e).map(hl)}channels(e){return this.control.database.query("SELECT * FROM regional_replication_channels WHERE topology_id=? ORDER BY kind,target_region").all(e).map(yl)}route(e){let t=this.control.database.query("SELECT * FROM regional_traffic_routes WHERE topology_id=?").get(e);return t?bl(t):void 0}updateTopology(e,t){let r=this.get(e);if(!r)throw Error("Regional topology was not found.");let n={...r,...t},i=this.now().toISOString();return this.control.database.run("UPDATE regional_topologies SET status=?,active_region=?,revision=?,regions=?,version=version+1,updated_at=? WHERE id=?",[n.status,n.activeRegion,n.revision??null,JSON.stringify(n.regions),i,e]),this.get(e)}updateTarget(e,t){let r=this.control.database.query("SELECT * FROM regional_targets WHERE id=?").get(e);if(!r)throw Error("Regional target was not found.");let n=hl(r),i={...n,...t},o=this.now().toISOString();return this.control.database.run("UPDATE regional_targets SET role=?,stack_id=?,stack_revision=?,status=?,health=?,last_healthy_at=?,version=version+1,updated_at=? WHERE id=?",[i.role,i.stackId??null,i.stackRevision??null,i.status,JSON.stringify(i.health),i.lastHealthyAt??null,o,e]),hl(this.control.database.query("SELECT * FROM regional_targets WHERE id=?").get(e))}updateChannel(e,t){let r=this.control.database.query("SELECT * FROM regional_replication_channels WHERE id=?").get(e);if(!r)throw Error("Replication channel was not found.");let n=yl(r),i={...n,...t},o=this.now().toISOString();return this.control.database.run("UPDATE regional_replication_channels SET status=?,checkpoint=?,lag_seconds=?,last_verified_at=?,version=version+1,updated_at=? WHERE id=?",[i.status,i.checkpoint??null,i.lagSeconds??null,i.lastVerifiedAt??null,o,e]),yl(this.control.database.query("SELECT * FROM regional_replication_channels WHERE id=?").get(e))}updateRoute(e,t){let r=this.control.database.query("SELECT * FROM regional_traffic_routes WHERE id=?").get(e);if(!r)throw Error("Traffic route was not found.");let n=bl(r),i={...n,...t},o=this.now().toISOString();return this.control.database.run("UPDATE regional_traffic_routes SET weights=?,desired_weights=?,status=?,provider_state=?,version=version+1,updated_at=? WHERE id=?",[JSON.stringify(i.weights),JSON.stringify(i.desiredWeights),i.status,JSON.stringify(i.providerState),o,e]),bl(this.control.database.query("SELECT * FROM regional_traffic_routes WHERE id=?").get(e))}createExecution(e){let t=this.id(),r=this.now().toISOString();return this.control.database.run("INSERT INTO regional_executions (id,topology_id,operation_id,kind,requested_region,revision,plan,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,'queued',?,?)",[t,e.topologyId,e.operationId??null,e.kind,e.requestedRegion??null,e.revision??null,JSON.stringify(e.plan),r,r]),this.execution(t)}execution(e){let t=this.control.database.query("SELECT * FROM regional_executions WHERE id=?").get(e);return t?eh(t):void 0}executions(e){return this.control.database.query("SELECT * FROM regional_executions WHERE topology_id=? ORDER BY created_at DESC").all(e).map(eh)}updateExecution(e,t){let r=this.execution(e);if(!r)throw Error("Regional execution was not found.");let n={...r,...t},i=this.now().toISOString();return this.control.database.run("UPDATE regional_executions SET operation_id=?,current_step=?,completed_steps=?,status=?,error=?,updated_at=? WHERE id=?",[n.operationId??null,n.currentStep??null,JSON.stringify(n.completedSteps),n.status,n.error??null,i,e]),this.execution(e)}}class fn{store;queue;constructor(e,t){this.store=e;this.queue=t??new b(e.control)}create(e){return this.store.create(e)}plan(e,t,r){if(!this.store.get(e))throw Error("Regional topology was not found.");let i=this.store.targets(e),o=this.store.channels(e);if(t==="rollout")return[...i.filter((s)=>s.role==="secondary").map((s)=>`apply:${s.region}`),...i.filter((s)=>s.role==="primary").map((s)=>`apply:${s.region}`),...o.map((s)=>`replicate:${s.kind}:${s.targetRegion}`),"traffic:activate"];if(t==="failover"||t==="failback")return[`health:${r}`,`replication:${r}`,`traffic:${r}`,`roles:${r}`];if(t==="destroy")return["traffic:drain",...i.filter((s)=>s.role==="secondary").map((s)=>`delete:${s.region}`),...i.filter((s)=>s.role==="primary").map((s)=>`delete:${s.region}`),"complete"];return["observe","repair"]}enqueue(e){let t=this.store.get(e.topologyId);if(!t)throw Error("Regional topology was not found.");if(["failover","failback"].includes(e.kind)&&(!e.targetRegion||!t.regions.some((o)=>o.region===e.targetRegion)))throw Error("A topology target region is required.");if(e.kind==="failover"&&e.targetRegion===t.activeRegion)throw Error("Target region is already active.");if((e.kind==="destroy"||e.deleteData)&&e.confirmation!==t.name)throw Error("Exact topology name confirmation is required.");if(e.deleteData&&t.dataPolicy.retainOnDestroy)throw Error("Topology policy requires regional data retention.");if(e.kind==="rollout"&&!/^[A-Za-z0-9._:@/-]{7,200}$/.test(e.revision??""))throw Error("An immutable revision is required.");let r=this.plan(t.id,e.kind,e.targetRegion),n=this.store.createExecution({topologyId:t.id,kind:e.kind,requestedRegion:e.targetRegion,revision:e.revision,plan:r}),i=this.queue.enqueue({projectId:t.projectId,environmentId:t.environmentId,kind:`region.${e.kind}`,input:{executionId:n.id,manifest:e.manifest??{},deleteData:e.deleteData===!0},lockKey:`regional-topology:${t.id}`,providerKey:"multi-region",timeoutSeconds:7200,cancellationMode:"provider_non_cancellable",resumePolicy:"requeue",maxAttempts:3}).operation;return this.store.updateExecution(n.id,{operationId:i.id}),{execution:this.store.execution(n.id),operation:i}}}var nC=(e)=>e&&typeof e==="object"&&!Array.isArray(e)?e:{};function th(e,t){let r=(a)=>{let m=t.find((E)=>E.provider===a.provider);if(!m)throw Error(`No ${a.provider} regional driver is configured.`);return m},n=(a,m,E)=>{a.throwIfCancellationRequested(),a.checkpoint(E,E),e.updateExecution(m.id,{status:"running",currentStep:E,completedSteps:[...e.execution(m.id).completedSteps,E]})},i=async(a,m)=>{let E=e.route(a.id);if(!E)throw Error("Regional traffic route was not found.");let k=e.targets(a.id).find((q)=>q.region===a.activeRegion)??e.targets(a.id)[0];if(!k)throw Error("Regional traffic target was not found.");e.updateRoute(E.id,{status:"applying",desiredWeights:m});let O=await r(k).applyTraffic({route:e.route(a.id),topology:a,weights:m});e.updateRoute(E.id,{status:Object.values(m).every((q)=>q===0)?"drained":"in_sync",weights:m,providerState:O.providerState})},o=async(a,m,E,k)=>{e.updateTopology(E.id,{status:"provisioning"});let O=m.revision,q=k.manifest??{},G=e.targets(E.id).sort((re,he)=>Number(re.role==="primary")-Number(he.role==="primary"));for(let re of G){n(a,m,`apply:${re.region}`),e.updateTarget(re.id,{status:"provisioning"});let he=await r(re).applyStack({target:re,revision:O,manifest:q,signal:a.signal}),ee=await r(re).health({target:e.updateTarget(re.id,{stackId:he.stackId,stackRevision:O})});if(!ee.healthy)throw Error(`Regional health gate failed in ${re.region}.`);e.updateTarget(re.id,{status:"ready",health:ee.evidence,lastHealthyAt:new Date().toISOString()})}for(let re of e.channels(E.id)){n(a,m,`replicate:${re.kind}:${re.targetRegion}`),e.updateChannel(re.id,{status:"configuring"});let he=G.find((at)=>at.region===re.sourceRegion),ee=await r(he).configureReplication({channel:re,topology:E}),Re=await r(he).verifyReplication({channel:e.updateChannel(re.id,{checkpoint:ee.checkpoint,lagSeconds:ee.lagSeconds}),topology:E});if(!Re.healthy||Re.lagSeconds>E.dataPolicy.maxLagSeconds)throw Error(`${re.kind} replication to ${re.targetRegion} exceeds the RPO.`);e.updateChannel(re.id,{status:"in_sync",checkpoint:Re.checkpoint,lagSeconds:Re.lagSeconds,lastVerifiedAt:new Date().toISOString()})}n(a,m,"traffic:activate");let Y=Object.fromEntries(E.regions.map((re)=>[re.region,re.region===E.activeRegion?100:0]));return await i(E,Y),e.updateTopology(E.id,{status:"ready",revision:O}),{revision:O,activeRegion:E.activeRegion}},s=async(a,m,E)=>{let k=m.requestedRegion,O=e.targets(E.id).find((Y)=>Y.region===k);if(!O)throw Error("Requested regional target was not found.");e.updateTopology(E.id,{status:m.kind==="failover"?"failing_over":"failing_back"}),n(a,m,`health:${k}`);let q=await r(O).health({target:O});if(!q.healthy)throw Error(`Target region ${k} is unhealthy.`);e.updateTarget(O.id,{status:"ready",health:q.evidence,lastHealthyAt:new Date().toISOString()}),n(a,m,`replication:${k}`);for(let Y of e.channels(E.id).filter((re)=>re.targetRegion===k)){let re=await r(O).verifyReplication({channel:Y,topology:E});if(!re.healthy||re.lagSeconds>E.dataPolicy.maxLagSeconds)throw Error(`${Y.kind} replication is outside the failover RPO.`);e.updateChannel(Y.id,{status:"in_sync",checkpoint:re.checkpoint,lagSeconds:re.lagSeconds,lastVerifiedAt:new Date().toISOString()})}n(a,m,`traffic:${k}`),await i(E,Object.fromEntries(E.regions.map((Y)=>[Y.region,Y.region===k?100:0]))),n(a,m,`roles:${k}`);let G=E.regions.map((Y)=>({...Y,role:Y.region===k?"primary":"secondary"}));for(let Y of e.targets(E.id))e.updateTarget(Y.id,{role:Y.region===k?"primary":"secondary"});return e.updateTopology(E.id,{status:m.kind==="failover"?"failed_over":"ready",activeRegion:k,regions:G}),{activeRegion:k}},c=async(a,m,E,k)=>{e.updateTopology(E.id,{status:"destroying"}),n(a,m,"traffic:drain"),await i(E,Object.fromEntries(E.regions.map((q)=>[q.region,0])));let O=k.deleteData!==!0;for(let q of e.targets(E.id).sort((G,Y)=>Number(G.role==="primary")-Number(Y.role==="primary")))n(a,m,`delete:${q.region}`),e.updateTarget(q.id,{status:"deleting"}),await r(q).deleteStack({target:q,retainData:O,signal:a.signal}),e.updateTarget(q.id,{status:"deleted"});return n(a,m,"complete"),e.updateTopology(E.id,{status:"destroyed"}),{destroyed:!0,dataRetained:O}},l=async(a)=>{let m=nC(a.operation.input),E=e.execution(String(m.executionId??""));if(!E)throw Error("Regional execution was not found.");let k=e.get(E.topologyId);if(!k)throw Error("Regional topology was not found.");try{let O;if(E.kind==="rollout")O=await o(a,E,k,m);else if(E.kind==="failover"||E.kind==="failback")O=await s(a,E,k);else if(E.kind==="destroy")O=await c(a,E,k,m);else throw Error("Regional reconciliation is not configured.");return e.updateExecution(E.id,{status:"succeeded",currentStep:void 0}),{executionId:E.id,...O}}catch(O){if(e.updateExecution(E.id,{status:a.cancellationRequested()?"cancelled":"failed",error:O instanceof Error?O.message:String(O)}),e.get(k.id)?.status!=="destroyed")e.updateTopology(k.id,{status:"failed"});throw O}};return{"region.rollout":l,"region.failover":l,"region.failback":l,"region.destroy":l,"region.reconcile":l}}class Sl{provider;reason;constructor(e,t="Configure a regional provider transport before executing this operation."){this.provider=e;this.reason=t}fail(){throw Error(this.reason)}async applyStack(){return this.fail()}async deleteStack(){this.fail()}async health(){return this.fail()}async configureReplication(){return this.fail()}async verifyReplication(){return this.fail()}async applyTraffic(){return this.fail()}}function Bi(e,t,r){return[e,t,r].map((n)=>encodeURIComponent(n)).join(":")}function iC(e){return Object.fromEntries(["start","stop","restart","redeploy","scale","logs","exec","inspect","files"].map((t)=>[t,{supported:!1,reason:e}]))}function us(e,t,r=["exec","files"]){let n=iC(t);for(let i of e)n[i]={supported:!0,requiresConfirmation:!["logs","inspect"].includes(i),requiresRecentAuth:r.includes(i)};return n}var oC=/(?:secret|password|passwd|token|api[_-]?key|private[_-]?key|credential|authorization|cookie)/i;function so(e){let t=String(e??"").trim().toLowerCase();if(["active","running","ready","healthy","available","steady","active:running"].includes(t))return"running";if(["activating","pending","provisioning","starting","created","initializing"].includes(t))return"starting";if(["deactivating","stopping","draining","terminating"].includes(t))return"stopping";if(["inactive","stopped","complete","completed","exited","disabled"].includes(t))return"stopped";if(["degraded","unhealthy","warning"].includes(t))return"degraded";if(["failed","dead","error","crashed","oomkilled"].includes(t))return"failed";return"unknown"}function oo(e){if(Array.isArray(e))return e.map((r)=>oo(r));if(!e||typeof e!=="object")return e;let t={};for(let[r,n]of Object.entries(e))t[r]=oC.test(r)?"[REDACTED]":oo(n);return t}function ls(e,t=new Date){if(!e)return;let r=new Date(e).getTime();return Number.isFinite(r)?Math.max(0,Math.floor((t.getTime()-r)/1000)):void 0}function rh(e){let t=Number(e);return Number.isFinite(t)&&t>=0?t:void 0}function sC(e){let t=String(e?.message??e);if(/(?:unauthorized|accessdenied|forbidden|credentials)/i.test(t))return"unauthorized";if(/(?:timeout|unreachable|econnrefused|enotfound|network)/i.test(t))return"unreachable";return"error"}async function nh(e,t={},r={}){let n=t.now??new Date,i=Math.max(100,r.timeoutMs??1e4),o=Math.max(1,r.staleAfterSeconds??60),s=await Promise.all(e.map(async(l)=>{try{let a=await Promise.race([l.discover({...t,now:n}),new Promise((m,E)=>setTimeout(()=>E(Error(`Runtime source ${l.id} timed out after ${i}ms`)),i))]);return{workloads:a,source:{id:l.id,provider:l.provider,status:"fresh",discoveredAt:n.toISOString(),staleAfterSeconds:o,itemCount:a.length}}}catch(a){return{workloads:[],source:{id:l.id,provider:l.provider,status:sC(a),discoveredAt:n.toISOString(),staleAfterSeconds:o,itemCount:0,message:String(a?.message??a).slice(0,500)}}}})),c=s.map((l)=>l.source);return{generatedAt:n.toISOString(),workloads:s.flatMap((l)=>l.workloads).sort((l,a)=>l.name.localeCompare(a.name)||l.id.localeCompare(a.id)),sources:c,degraded:c.some((l)=>l.status!=="fresh")}}function aC(e,t){if(!t)return e;return e.startsWith(t)?e.slice(t.length):e}function ih(e,t,r){let n=aC(e,t);return`${r??""}${n}`}function oh(e,t,r){if(r&&r.some((n)=>e.startsWith(n)))return!1;if(t&&t.length>0)return t.some((n)=>e.startsWith(n));return!0}async function cC(e,t,r){let n=0,i=[],o=Math.max(1,Math.min(t,e.length||1));for(let s=0;s<o;s++)i.push((async()=>{while(!0){let c=n++;if(c>=e.length)return;await r(e[c],c)}})());await Promise.all(i)}function sh(e){if(e.client)return e.client;return ah({provider:e.provider,region:e.region,endpoint:e.endpoint,forcePathStyle:e.forcePathStyle,credentials:e.credentials})}async function xo(e){let t=e.concurrency??8,r=sh(e.from),n=sh(e.to),i=await r.listAllObjects({bucket:e.from.bucket,prefix:e.from.prefix}),o={copied:0,skipped:0,excluded:0,bytesCopied:0,errors:[],excludedKeys:[],deleted:[]},s=[];for(let m of i){if(!oh(m.Key,e.include,e.exclude)){o.excluded++,o.excludedKeys.push(m.Key);continue}s.push({source:m,destKey:ih(m.Key,e.from.prefix,e.to.prefix)})}if(e.dryRun){o.plan=s.map(({source:k,destKey:O})=>({key:k.Key,destKey:O,size:k.Size}));let m=i.length,E=0;for(let k of i){E++;let O=!oh(k.Key,e.include,e.exclude);e.onProgress?.({key:k.Key,destKey:O?"":ih(k.Key,e.from.prefix,e.to.prefix),size:k.Size,action:O?"excluded":"planned",index:E,total:m})}return o}let c=s.length,l=0;await cC(s,t,async({source:m,destKey:E})=>{let k=++l;try{if(!e.force){let G=await n.headObject(e.to.bucket,E);if(G&&G.ContentLength===m.Size){o.skipped++,e.onProgress?.({key:m.Key,destKey:E,size:m.Size,action:"skipped",index:k,total:c});return}}let{body:O,contentType:q}=await r.getObjectBytes(e.from.bucket,m.Key);await n.putObject({bucket:e.to.bucket,key:E,body:O,contentType:q}),o.copied++,o.bytesCopied+=O.byteLength,e.onProgress?.({key:m.Key,destKey:E,size:m.Size,action:"copied",index:k,total:c})}catch(O){o.errors.push({key:m.Key,message:O?.message??String(O)}),e.onProgress?.({key:m.Key,destKey:E,size:m.Size,action:"error",index:k,total:c})}});let a=new Set(s.map((m)=>m.destKey));if(e.deleteExtraneous){let E=(await n.listAllObjects({bucket:e.to.bucket,prefix:e.to.prefix})).filter((k)=>!a.has(k.Key)).map((k)=>k.Key);for(let k of E)try{await n.deleteObject(e.to.bucket,k),o.deleted.push(k)}catch(O){o.errors.push({key:k,message:`delete failed: ${O?.message??String(O)}`})}}if(e.verify){let m=await n.listAllObjects({bucket:e.to.bucket,prefix:e.to.prefix}),E=new Map(m.map((G)=>[G.Key,G.Size])),k=[],O=[],q=0;for(let{source:G,destKey:Y}of s){if(!E.has(Y)){k.push(Y);continue}let re=E.get(Y);if(re!==G.Size){O.push({key:Y,expected:G.Size,actual:re});continue}q++}o.verification={ok:k.length===0&&O.length===0,matched:q,missing:k,sizeMismatches:O}}return o}var dC={aws:"us-east-1",backblaze:"us-west-004",hetzner:"fsn1"};function uC(e,t){switch(e){case"backblaze":return`s3.${t}.backblazeb2.com`;case"hetzner":return`${t}.your-objectstorage.com`;case"aws":default:return}}function ni(...e){for(let t of e){let r=process.env[t];if(r)return r}return}function lC(e,t){if(t?.accessKeyId&&t.secretAccessKey)return t;let r,n;if(e==="backblaze")r=ni("B2_APPLICATION_KEY_ID","B2_KEY_ID","S3_ACCESS_KEY_ID","AWS_ACCESS_KEY_ID"),n=ni("B2_APPLICATION_KEY","B2_SECRET_KEY","S3_SECRET_ACCESS_KEY","AWS_SECRET_ACCESS_KEY");else if(e==="hetzner")r=ni("HETZNER_S3_ACCESS_KEY","HETZNER_ACCESS_KEY","S3_ACCESS_KEY_ID","AWS_ACCESS_KEY_ID"),n=ni("HETZNER_S3_SECRET_KEY","HETZNER_SECRET_KEY","S3_SECRET_ACCESS_KEY","AWS_SECRET_ACCESS_KEY");else r=ni("S3_ACCESS_KEY_ID"),n=ni("S3_SECRET_ACCESS_KEY");if(r&&n)return{accessKeyId:r,secretAccessKey:n,sessionToken:ni("AWS_SESSION_TOKEN")};return}function pC(e={}){let t=e.provider||ni("OBJECT_STORAGE_PROVIDER","STORAGE_PROVIDER")||"aws",r=e.region||(t==="backblaze"?ni("B2_REGION"):void 0)||(t==="hetzner"?ni("HETZNER_S3_REGION","HETZNER_REGION"):void 0)||ni("S3_REGION","AWS_REGION","AWS_DEFAULT_REGION")||dC[t],n=e.endpoint||ni("S3_ENDPOINT")||uC(t,r),i=e.forcePathStyle??ni("S3_FORCE_PATH_STYLE")==="true",o=lC(t,e.credentials),s=(c)=>{let l=n||`s3.${r}.amazonaws.com`;return i?`https://${l}/${c}`:`https://${c}.${l}`};return{provider:t,region:r,endpoint:n,forcePathStyle:i,credentials:o,profile:e.profile,publicBaseUrl:s}}function ah(e={}){let t=pC(e),r={endpoint:t.endpoint,forcePathStyle:t.forcePathStyle,credentials:t.credentials};return new f(t.region,t.profile,r)}class It{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u(void 0,{profile:t})}async describeServices(e){let t={cluster:e.cluster,services:e.services};return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DescribeServices","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async listServices(e,t={}){let r={cluster:e,...t};return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.ListServices","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)})}async listTasks(e,t,r={}){let n={cluster:e,...r};if(t)n.serviceName=t;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.ListTasks","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(n)})}async describeTasks(e,t){let r={cluster:e,tasks:t};return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DescribeTasks","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)})}async updateService(e){let t={cluster:e.cluster,service:e.service};if(e.forceNewDeployment!==void 0)t.forceNewDeployment=e.forceNewDeployment;if(e.desiredCount!==void 0)t.desiredCount=e.desiredCount;if(e.taskDefinition)t.taskDefinition=e.taskDefinition;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.UpdateService","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async createService(e){let t={cluster:e.cluster,serviceName:e.serviceName,taskDefinition:e.taskDefinition,desiredCount:e.desiredCount};if(e.launchType)t.launchType=e.launchType;if(e.networkConfiguration)t.networkConfiguration=e.networkConfiguration;if(e.loadBalancers)t.loadBalancers=e.loadBalancers;if(e.healthCheckGracePeriodSeconds!==void 0)t.healthCheckGracePeriodSeconds=e.healthCheckGracePeriodSeconds;if(e.deploymentConfiguration)t.deploymentConfiguration=e.deploymentConfiguration;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.CreateService","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async deleteService(e){let t={cluster:e.cluster,service:e.service};if(e.force!==void 0)t.force=e.force;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DeleteService","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async listClusters(e={}){return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.ListClusters","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(e)})}async describeClusters(e){let t={clusters:e,include:["ATTACHMENTS","CONFIGURATIONS","SETTINGS","STATISTICS","TAGS"]};return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DescribeClusters","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async stopTask(e){let t={cluster:e.cluster,task:e.task};if(e.reason)t.reason=e.reason;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.StopTask","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async runTask(e){let t={cluster:e.cluster,taskDefinition:e.taskDefinition};if(e.count!==void 0)t.count=e.count;if(e.launchType)t.launchType=e.launchType;if(e.networkConfiguration)t.networkConfiguration=e.networkConfiguration;if(e.overrides)t.overrides=e.overrides;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.RunTask","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async registerTaskDefinition(e){return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.RegisterTaskDefinition","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(e)})}async deregisterTaskDefinition(e){return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DeregisterTaskDefinition","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({taskDefinition:e})})}async describeTaskDefinition(e){return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.DescribeTaskDefinition","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({taskDefinition:e,include:["TAGS"]})})}async listTaskDefinitionFamilies(e){let t={};if(e?.familyPrefix)t.familyPrefix=e.familyPrefix;if(e?.status)t.status=e.status;return await this.client.request({service:"ecs",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerServiceV20141113.ListTaskDefinitionFamilies","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})}async waitForServiceStable(e,t,r=40,n=15000){for(let i=0;i<r;i++){let s=(await this.describeServices({cluster:e,services:[t]})).services?.[0];if(s){let c=s.deployments?.find((l)=>l.status==="PRIMARY");if(c&&c.runningCount===c.desiredCount&&s.deployments?.length===1)return!0}await new Promise((c)=>setTimeout(c,n))}return!1}async forceNewDeployment(e,t){return this.updateService({cluster:e,service:t,forceNewDeployment:!0})}async scaleService(e,t,r){return this.updateService({cluster:e,service:t,desiredCount:r})}}class ce{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}buildFormBody(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,n])=>`${encodeURIComponent(r)}=${encodeURIComponent(n)}`).join("&")}async createTopic(e){let t={Action:"CreateTopic",Version:"2010-03-31",Name:e.Name};if(e.DisplayName)t["Attributes.entry.1.key"]="DisplayName",t["Attributes.entry.1.value"]=e.DisplayName;if(e.Tags)e.Tags.forEach((n,i)=>{t[`Tags.member.${i+1}.Key`]=n.Key,t[`Tags.member.${i+1}.Value`]=n.Value});if(e.Attributes){let n=e.DisplayName?2:1;Object.entries(e.Attributes).forEach(([i,o])=>{t[`Attributes.entry.${n}.key`]=i,t[`Attributes.entry.${n}.value`]=o,n++})}let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)});return{TopicArn:r?.CreateTopicResponse?.CreateTopicResult?.TopicArn||r?.TopicArn}}async deleteTopic(e){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"DeleteTopic",Version:"2010-03-31",TopicArn:e})})}async listTopics(e){let t={Action:"ListTopics",Version:"2010-03-31"};if(e)t.NextToken=e;let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)}),n=r?.ListTopicsResponse?.ListTopicsResult||r?.ListTopicsResult,i=n?.Topics?.member;return{Topics:Array.isArray(i)?i:i?[i]:[],NextToken:n?.NextToken}}async getTopicAttributes(e){let r=(await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"GetTopicAttributes",Version:"2010-03-31",TopicArn:e})}))?.GetTopicAttributesResponse?.GetTopicAttributesResult?.Attributes?.entry,n={TopicArn:e};if(Array.isArray(r))r.forEach((i)=>{n[i.key]=i.value});return n}async setTopicAttributes(e){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"SetTopicAttributes",Version:"2010-03-31",TopicArn:e.TopicArn,AttributeName:e.AttributeName,AttributeValue:e.AttributeValue})})}async subscribe(e){let t={Action:"Subscribe",Version:"2010-03-31",TopicArn:e.TopicArn,Protocol:e.Protocol,Endpoint:e.Endpoint};if(e.ReturnSubscriptionArn)t.ReturnSubscriptionArn="true";if(e.Attributes){let n=1;Object.entries(e.Attributes).forEach(([i,o])=>{t[`Attributes.entry.${n}.key`]=i,t[`Attributes.entry.${n}.value`]=o,n++})}let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)});return{SubscriptionArn:r?.SubscribeResponse?.SubscribeResult?.SubscriptionArn||r?.SubscriptionArn}}async unsubscribe(e){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"Unsubscribe",Version:"2010-03-31",SubscriptionArn:e})})}async listSubscriptionsByTopic(e,t){let r={Action:"ListSubscriptionsByTopic",Version:"2010-03-31",TopicArn:e};if(t)r.NextToken=t;let n=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(r)}),i=n?.ListSubscriptionsByTopicResponse?.ListSubscriptionsByTopicResult?.Subscriptions?.member;return{Subscriptions:Array.isArray(i)?i:i?[i]:[],NextToken:n?.ListSubscriptionsByTopicResponse?.ListSubscriptionsByTopicResult?.NextToken}}async publish(e){let t={Action:"Publish",Version:"2010-03-31",Message:e.Message};if(e.TopicArn)t.TopicArn=e.TopicArn;if(e.TargetArn)t.TargetArn=e.TargetArn;if(e.PhoneNumber)t.PhoneNumber=e.PhoneNumber;if(e.Subject)t.Subject=e.Subject;if(e.MessageStructure)t.MessageStructure=e.MessageStructure;if(e.MessageAttributes){let n=1;Object.entries(e.MessageAttributes).forEach(([i,o])=>{if(t[`MessageAttributes.entry.${n}.Name`]=i,t[`MessageAttributes.entry.${n}.Value.DataType`]=o.DataType,o.StringValue)t[`MessageAttributes.entry.${n}.Value.StringValue`]=o.StringValue;if(o.BinaryValue)t[`MessageAttributes.entry.${n}.Value.BinaryValue`]=o.BinaryValue;n++})}let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)});return{MessageId:r?.PublishResponse?.PublishResult?.MessageId||r?.MessageId}}async publishSMS(e,t,r){let n={};if(r)n["AWS.SNS.SMS.SenderID"]={DataType:"String",StringValue:r};return this.publish({PhoneNumber:e,Message:t,MessageAttributes:Object.keys(n).length>0?n:void 0})}async subscribeEmail(e,t){return this.subscribe({TopicArn:e,Protocol:"email",Endpoint:t})}async subscribeLambda(e,t){return this.subscribe({TopicArn:e,Protocol:"lambda",Endpoint:t})}async subscribeSqs(e,t,r){let n={};if(r)n.RawMessageDelivery="true";return this.subscribe({TopicArn:e,Protocol:"sqs",Endpoint:t,Attributes:Object.keys(n).length>0?n:void 0})}async subscribeHttp(e,t,r){let n=t.startsWith("https")?"https":"http",i={};if(r)i.RawMessageDelivery="true";return this.subscribe({TopicArn:e,Protocol:n,Endpoint:t,Attributes:Object.keys(i).length>0?i:void 0})}async subscribeSms(e,t){return this.subscribe({TopicArn:e,Protocol:"sms",Endpoint:t})}async topicExists(e){try{return await this.getTopicAttributes(e),!0}catch(t){if(t.code==="NotFound"||t.statusCode===404)return!1;throw t}}async getSMSAttributes(){let t=(await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"GetSMSAttributes",Version:"2010-03-31"})}))?.GetSMSAttributesResponse?.GetSMSAttributesResult?.attributes?.entry,r={};if(Array.isArray(t))t.forEach((n)=>{r[n.key]=n.value});else if(t)r[t.key]=t.value;return r}async setSMSAttributes(e){let t={Action:"SetSMSAttributes",Version:"2010-03-31"},r=1;Object.entries(e).forEach(([n,i])=>{if(i!==void 0)t[`attributes.entry.${r}.key`]=n,t[`attributes.entry.${r}.value`]=i,r++}),await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)})}async checkIfPhoneNumberIsOptedOut(e){return(await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"CheckIfPhoneNumberIsOptedOut",Version:"2010-03-31",phoneNumber:e})}))?.CheckIfPhoneNumberIsOptedOutResponse?.CheckIfPhoneNumberIsOptedOutResult?.isOptedOut==="true"}async listPhoneNumbersOptedOut(e){let t={Action:"ListPhoneNumbersOptedOut",Version:"2010-03-31"};if(e)t.nextToken=e;let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)}),n=r?.ListPhoneNumbersOptedOutResponse?.ListPhoneNumbersOptedOutResult?.phoneNumbers?.member;return{phoneNumbers:Array.isArray(n)?n:n?[n]:[],nextToken:r?.ListPhoneNumbersOptedOutResponse?.ListPhoneNumbersOptedOutResult?.nextToken}}async optInPhoneNumber(e){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"OptInPhoneNumber",Version:"2010-03-31",phoneNumber:e})})}async listSMSSandboxPhoneNumbers(e){let t={Action:"ListSMSSandboxPhoneNumbers",Version:"2010-03-31"};if(e)t.NextToken=e;let r=await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody(t)}),n=r?.ListSMSSandboxPhoneNumbersResponse?.ListSMSSandboxPhoneNumbersResult?.PhoneNumbers?.member;return{PhoneNumbers:Array.isArray(n)?n:n?[n]:[],NextToken:r?.ListSMSSandboxPhoneNumbersResponse?.ListSMSSandboxPhoneNumbersResult?.NextToken}}async createSMSSandboxPhoneNumber(e,t){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"CreateSMSSandboxPhoneNumber",Version:"2010-03-31",PhoneNumber:e,LanguageCode:t||"en-US"})})}async verifySMSSandboxPhoneNumber(e,t){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"VerifySMSSandboxPhoneNumber",Version:"2010-03-31",PhoneNumber:e,OneTimePassword:t})})}async deleteSMSSandboxPhoneNumber(e){await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"DeleteSMSSandboxPhoneNumber",Version:"2010-03-31",PhoneNumber:e})})}async getSMSSandboxAccountStatus(){return{IsInSandbox:(await this.client.request({service:"sns",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildFormBody({Action:"GetSMSSandboxAccountStatus",Version:"2010-03-31"})}))?.GetSMSSandboxAccountStatusResponse?.GetSMSSandboxAccountStatusResult?.IsInSandbox==="true"}}}class z{client;region;endpoint;constructor(e="us-east-1",t){this.region=e,this.endpoint=t?.endpoint,this.client=new u}async request(e,t){if(this.endpoint){let r=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/x-amz-json-1.0","X-Amz-Target":`DynamoDB_20120810.${e}`},body:JSON.stringify(t)});if(!r.ok){let n=await r.text();throw Error(`DynamoDB request failed: ${r.status} ${n}`)}return r.json()}return this.client.request({service:"dynamodb",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.0","X-Amz-Target":`DynamoDB_20120810.${e}`},body:JSON.stringify(t)})}async createTable(e){return this.request("CreateTable",e)}async deleteTable(e){return this.request("DeleteTable",e)}async describeTable(e){return this.request("DescribeTable",e)}async listTables(e){return this.request("ListTables",e||{})}async putItem(e){return this.request("PutItem",e)}async getItem(e){return this.request("GetItem",e)}async updateItem(e){return this.request("UpdateItem",e)}async deleteItem(e){return this.request("DeleteItem",e)}async query(e){return this.request("Query",e)}async scan(e){return this.request("Scan",e)}async batchWriteItem(e){return this.request("BatchWriteItem",e)}async batchGetItem(e){return this.request("BatchGetItem",e)}async updateTimeToLive(e){return this.request("UpdateTimeToLive",e)}static marshal(e){let t={};for(let[r,n]of Object.entries(e))t[r]=z.marshalValue(n);return t}static marshalValue(e){if(e===null||e===void 0)return{NULL:!0};if(typeof e==="string")return{S:e};if(typeof e==="number")return{N:String(e)};if(typeof e==="boolean")return{BOOL:e};if(Array.isArray(e))return{L:e.map((t)=>z.marshalValue(t))};if(typeof e==="object")return{M:z.marshal(e)};return{S:String(e)}}static unmarshal(e){let t={};for(let[r,n]of Object.entries(e))t[r]=z.unmarshalValue(n);return t}static unmarshalValue(e){if(e.S!==void 0)return e.S;if(e.N!==void 0)return Number(e.N);if(e.BOOL!==void 0)return e.BOOL;if(e.NULL!==void 0)return null;if(e.L!==void 0)return e.L.map((t)=>z.unmarshalValue(t));if(e.M!==void 0)return z.unmarshal(e.M);if(e.SS!==void 0)return e.SS;if(e.NS!==void 0)return e.NS.map(Number);return null}}class me{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async request(e,t){return this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`AWSEvents.${e}`},body:JSON.stringify(t)})}async putRule(e){return this.request("PutRule",e)}async deleteRule(e){return this.request("DeleteRule",e)}async describeRule(e){return this.request("DescribeRule",e)}async listRules(e){return this.request("ListRules",e||{})}async listEventBuses(e){return this.request("ListEventBuses",e||{})}async enableRule(e){return this.request("EnableRule",e)}async disableRule(e){return this.request("DisableRule",e)}async putTargets(e){return this.request("PutTargets",e)}async removeTargets(e){return this.request("RemoveTargets",e)}async listTargetsByRule(e){return this.request("ListTargetsByRule",e)}async putEvents(e){return this.request("PutEvents",e)}async createSchedule(e){return this.client.request({service:"scheduler",region:this.region,method:"POST",path:`/schedules/${e.Name}`,headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}}class xe{client;region;constructor(e="us-east-1",t){this.region=e,this.client=new u}async createRule(e){let t={Action:"PutRule",Name:e.name,ScheduleExpression:e.scheduleExpression,Version:"2015-10-07"};if(e.description)t.Description=e.description;if(e.state)t.State=e.state;else t.State="ENABLED";return{RuleArn:(await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.PutRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Name:e.name,ScheduleExpression:e.scheduleExpression,State:e.state||"ENABLED",Description:e.description})})).RuleArn}}async putTargets(e,t){await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.PutTargets","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Rule:e,Targets:t})})}async listRules(e){let t={};if(e)t.NamePrefix=e;return{Rules:(await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.ListRules","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(t)})).Rules||[]}}async describeRule(e){let t=await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.DescribeRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Name:e})});return{Name:t.Name,Arn:t.Arn,ScheduleExpression:t.ScheduleExpression,State:t.State,Description:t.Description}}async listTargetsByRule(e){return{Targets:(await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.ListTargetsByRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Rule:e})})).Targets||[]}}async deleteRule(e,t){if(t)try{let r=await this.listTargetsByRule(e);if(r.Targets&&r.Targets.length>0)await this.removeTargets(e,r.Targets.map((n)=>n.Id))}catch{}await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.DeleteRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Name:e,Force:t||!1})})}async removeTargets(e,t){await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.RemoveTargets","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Rule:e,Ids:t})})}async enableRule(e){await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.EnableRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Name:e})})}async disableRule(e){await this.client.request({service:"events",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AWSEvents.DisableRule","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify({Name:e})})}async createLambdaSchedule(e){let t=await this.createRule({name:e.name,scheduleExpression:e.scheduleExpression,description:e.description,state:"ENABLED"});return await this.putTargets(e.name,[{Id:"1",Arn:e.functionArn,Input:e.input}]),t}async createEcsSchedule(e){let t=await this.createRule({name:e.name,scheduleExpression:e.scheduleExpression,description:e.description,state:"ENABLED"});return await this.putTargets(e.name,[{Id:"1",Arn:e.clusterArn,RoleArn:e.roleArn,Input:JSON.stringify({containerOverrides:[]})}]),t}async listSchedules(e){let t={};if(e?.NamePrefix)t.NamePrefix=e.NamePrefix;if(e?.State)t.State=e.State;let r=e?.GroupName||"default";return{Schedules:(await this.client.request({service:"scheduler",region:this.region,method:"GET",path:"/schedules",queryParams:{...t,ScheduleGroup:r}}))?.Schedules||[]}}async getSchedule(e){try{let t={};if(e.GroupName)t.groupName=e.GroupName;return await this.client.request({service:"scheduler",region:this.region,method:"GET",path:`/schedules/${encodeURIComponent(e.Name)}`,queryParams:Object.keys(t).length>0?t:void 0})}catch(t){if(t.statusCode===404||t.code==="ResourceNotFoundException")return null;throw t}}async createSchedule(e){let t={ScheduleExpression:e.ScheduleExpression,FlexibleTimeWindow:e.FlexibleTimeWindow,Target:e.Target};if(e.GroupName)t.GroupName=e.GroupName;if(e.ScheduleExpressionTimezone)t.ScheduleExpressionTimezone=e.ScheduleExpressionTimezone;if(e.Description)t.Description=e.Description;if(e.State)t.State=e.State;if(e.StartDate)t.StartDate=e.StartDate.toISOString();if(e.EndDate)t.EndDate=e.EndDate.toISOString();return{ScheduleArn:(await this.client.request({service:"scheduler",region:this.region,method:"POST",path:`/schedules/${encodeURIComponent(e.Name)}`,headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))?.ScheduleArn||""}}async updateSchedule(e){let t={};if(e.GroupName)t.GroupName=e.GroupName;if(e.ScheduleExpression)t.ScheduleExpression=e.ScheduleExpression;if(e.ScheduleExpressionTimezone)t.ScheduleExpressionTimezone=e.ScheduleExpressionTimezone;if(e.Description!==void 0)t.Description=e.Description;if(e.State)t.State=e.State;if(e.FlexibleTimeWindow)t.FlexibleTimeWindow=e.FlexibleTimeWindow;if(e.Target)t.Target=e.Target;return{ScheduleArn:(await this.client.request({service:"scheduler",region:this.region,method:"PUT",path:`/schedules/${encodeURIComponent(e.Name)}`,headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))?.ScheduleArn||""}}async deleteSchedule(e){let t={};if(e.GroupName)t.groupName=e.GroupName;await this.client.request({service:"scheduler",region:this.region,method:"DELETE",path:`/schedules/${encodeURIComponent(e.Name)}`,queryParams:Object.keys(t).length>0?t:void 0})}async listScheduleGroups(e){let t={};if(e?.NamePrefix)t.NamePrefix=e.NamePrefix;return{ScheduleGroups:(await this.client.request({service:"scheduler",region:this.region,method:"GET",path:"/schedule-groups",queryParams:Object.keys(t).length>0?t:void 0}))?.ScheduleGroups||[]}}}function Ks(e){return e?.split("/").at(-1)??e?.split(":").at(-1)??"unknown"}function ch(e,t,r,n="ecs:aws",i=[]){let o=r.now??new Date;return e.map((s)=>{let c=s.serviceName??Ks(s.serviceArn),l=t.filter((re)=>!s.clusterArn||re.clusterArn===s.clusterArn),a=l.some((re)=>!!re.group)?l.filter((re)=>re.group===`service:${c}`):l,m=s.status==="ACTIVE"?(s.runningCount??0)<(s.desiredCount??0)?"degraded":"running":so(s.status),E=i.find((re)=>re.taskDefinitionArn===s.taskDefinition),k=Array.isArray(E?.containerDefinitions)?E.containerDefinitions:[],O=[...new Set(k.map((re)=>re.logConfiguration?.options?.["awslogs-group"]).filter((re)=>typeof re==="string"))],q=k.flatMap((re)=>(re.mountPoints??[]).map((he)=>({source:he.sourceVolume,target:he.containerPath,type:"volume",readOnly:!!he.readOnly}))),G=k.flatMap((re)=>(re.portMappings??[]).map((he,ee)=>({id:`${re.name??"container"}:${ee}`,name:re.name,mode:E?.networkMode,ports:[{container:he.containerPort,host:he.hostPort,protocol:he.protocol}]}))),Y=r.project&&r.environment&&c.startsWith(`${r.project}-${r.environment}-`)?c.slice(`${r.project}-${r.environment}-`.length):c;return{id:Bi("ecs",n,s.serviceArn??c),provider:"ecs",kind:"service",name:c,status:m,rawStatus:s.status,health:m==="running"?"healthy":m==="failed"||m==="degraded"?"unhealthy":"unknown",desiredReplicas:s.desiredCount,runningReplicas:s.runningCount,image:k[0]?.image,runtime:s.launchType??"ECS",version:Ks(s.taskDefinition),ageSeconds:ls(s.deployments?.[0]?.createdAt,o),restartCount:0,tags:{},links:{project:r.project,environment:r.environment,service:Y,release:Ks(s.taskDefinition),providerId:s.serviceArn},replicas:a.map((re)=>{let he=so(re.lastStatus);return{id:Bi("ecs",n,re.taskArn??Ks(re.taskArn)),name:Ks(re.taskArn),status:he,rawStatus:re.lastStatus,createdAt:re.createdAt,startedAt:re.startedAt,stoppedAt:re.stoppedAt,host:re.containerInstanceArn,containers:(re.containers??[]).map((ee)=>({id:ee.containerArn??ee.name??"container",name:ee.name??"container",image:k.find((Re)=>Re.name===ee.name)?.image,imageDigest:ee.imageDigest,status:so(ee.lastStatus),rawStatus:ee.lastStatus,exitCode:ee.exitCode,reason:ee.reason,runtime:"ecs"}))}}),networks:G,mounts:q,capabilities:us(["start","stop","restart","redeploy","scale","inspect",...O.length?["logs"]:[]],"This ECS runtime does not expose exec or file transfer; logs require an awslogs task-definition driver"),config:oo({clusterArn:s.clusterArn,taskDefinition:s.taskDefinition,launchType:s.launchType,pendingCount:s.pendingCount,deployments:s.deployments,logGroups:O,executionRoleArn:E?.executionRoleArn,taskRoleArn:E?.taskRoleArn,cpu:E?.cpu,memory:E?.memory}),discoveredAt:o.toISOString(),sourceId:n}})}function dh(e,t,r="lambda:aws"){let n=t.now??new Date;return e.map((i)=>{let o=i.FunctionName??Ks(i.FunctionArn),s=i.State==="Active"?"running":so(i.State);return{id:Bi("lambda",r,i.FunctionArn??o),provider:"lambda",kind:"function",name:o,status:s,rawStatus:i.State,health:s==="running"?"healthy":s==="failed"?"unhealthy":"unknown",desiredReplicas:void 0,runningReplicas:void 0,image:void 0,runtime:i.Runtime,version:i.Version,architecture:i.Architectures?.join(", "),ageSeconds:ls(i.LastModified,n),restartCount:0,tags:{},links:{project:t.project,environment:t.environment,service:o,providerId:i.FunctionArn},resources:{memoryLimitBytes:i.MemorySize==null?void 0:i.MemorySize*1024*1024},replicas:[],networks:[],mounts:[],capabilities:us(["logs","inspect"],"Lambda has no persistent process to start, stop, restart, exec, or browse files; deploy a release to replace code"),config:oo({handler:i.Handler,timeout:i.Timeout,codeSize:i.CodeSize,stateReason:i.StateReason,environmentKeys:Object.keys(i.Environment?.Variables??{})}),discoveredAt:n.toISOString(),sourceId:r}})}function gC(e){let t=e.trim();if(!t)return[];let r=JSON.parse(t);if(!Array.isArray(r))throw Error("Docker inspect output must be an array");return r.filter((n)=>n&&typeof n.Id==="string")}function mC(e){let t=Object.entries(e.NetworkSettings?.Ports??{}).flatMap(([r,n])=>{let[i,o]=r.split("/");return(n??[]).map((s)=>({container:Number(i)||void 0,host:Number(s.HostPort)||void 0,protocol:o,address:s.HostIp}))});return Object.entries(e.NetworkSettings?.Networks??{}).map(([r,n])=>({id:n.NetworkID||r,name:r,mode:e.HostConfig?.NetworkMode,addresses:[n.IPAddress,n.GlobalIPv6Address].filter(Boolean),ports:t}))}function fC(e){return(e.Mounts??[]).filter((t)=>!!t.Destination).map((t)=>({source:t.Source,target:t.Destination,type:t.Type,readOnly:t.RW===!1}))}function hC(e,t,r=t.server??"local"){let n=t.now??new Date;return e.map((i)=>{let o=i.State?.OOMKilled?"oomkilled":i.State?.Restarting?"starting":i.State?.Status,s=so(o),c=(i.Name??i.Id.slice(0,12)).replace(/^\//,""),l=i.Config?.Labels??{},a=fC(i),m=mC(i),E={id:i.Id,name:c,image:i.Config?.Image,imageDigest:i.Image,runtime:"docker",status:s,rawStatus:o,exitCode:i.State?.ExitCode,reason:i.State?.Error,resources:{memoryLimitBytes:i.HostConfig?.Memory||void 0},networks:m,mounts:a};return{id:Bi("docker",r,i.Id),provider:"docker",kind:"container",name:c,status:s,rawStatus:o,health:s==="running"?"healthy":s==="failed"?"unhealthy":"unknown",desiredReplicas:1,runningReplicas:s==="running"?1:0,image:i.Config?.Image,runtime:"docker",ageSeconds:ls(i.State?.StartedAt,n),restartCount:i.RestartCount??0,tags:l,links:{project:t.project,environment:t.environment,server:t.server??r.replace(/^docker:/,""),service:l["com.docker.compose.service"]??l["ts-cloud.service"]??c,release:l["ts-cloud.release"],providerId:i.Id},resources:E.resources,replicas:[{id:Bi("docker",r,`${i.Id}:0`),name:c,status:s,rawStatus:o,startedAt:i.State?.StartedAt,stoppedAt:i.State?.FinishedAt,restartCount:i.RestartCount,containers:[E],resources:E.resources}],networks:m,mounts:a,capabilities:us(["start","stop","restart","logs","exec","inspect","files"],"Use the owning Compose service for redeploy and scale"),config:oo({image:i.Config?.Image,labels:l,environmentKeys:(i.Config?.Env??[]).map((k)=>k.split("=",1)[0]),networkMode:i.HostConfig?.NetworkMode}),discoveredAt:n.toISOString(),sourceId:r}})}class vl{inspect;id;provider="docker";constructor(e,t="docker:local"){this.inspect=e;this.id=t}async discover(e){return hC(gC(await this.inspect(e)),e,this.id)}}function yC(e){let t=[];for(let r of e.split(`
|
|
120
|
+
`)){if(!r.startsWith("TSCLOUD_SYSTEMD\t"))continue;let[,n,i,o,s,c,l,a,m,E,k,O,q,G]=r.split("\t");if(!n||!/^[A-Za-z0-9_.@:-]+\.service$/.test(n))continue;t.push({unit:n,load:i,active:o,sub:s,description:c,enabled:l,pid:Number(a)||void 0,memoryBytes:rh(m),restartCount:Number(E)||0,activeSince:k||void 0,fragmentPath:O||void 0,workingDirectory:q?.startsWith("/")?q:void 0,user:G||void 0})}return t}function bC(e,t,r=t.server??"local"){let n=t.now??new Date;return e.map((i)=>{let o=so(i.active==="active"?i.sub||i.active:i.active),s=i.unit.replace(/\.service$/,""),c=/^(.*?) (?:release [^ ]+|queue worker|daemon |scheduler)(?: |$)/.exec(i.description??"")?.[1]??(t.project&&s.startsWith(`${t.project}-`)?s.slice(t.project.length+1).split("@",1)[0]:void 0),l=s.includes("@")?s.slice(s.indexOf("@")+1):void 0,a=i.workingDirectory?[{target:i.workingDirectory,type:"working-directory"}]:[],m=["start","stop","restart","logs","exec","inspect",...a.length?["files"]:[]];return{id:Bi("systemd",r,i.unit),provider:"systemd",kind:"service",name:s,displayName:i.description||s,status:o,rawStatus:[i.load,i.active,i.sub].filter(Boolean).join("/"),health:o==="running"?"healthy":o==="failed"?"unhealthy":"unknown",desiredReplicas:1,runningReplicas:o==="running"?1:0,ageSeconds:ls(i.activeSince,n),restartCount:i.restartCount,tags:{enabled:i.enabled??"unknown"},links:{project:t.project,environment:t.environment,server:t.server??r.replace(/^systemd:/,""),service:c,release:l,providerId:i.unit},resources:{memoryBytes:i.memoryBytes},replicas:[{id:Bi("systemd",r,`${i.unit}:main`),name:"main",status:o,pid:i.pid,startedAt:i.activeSince,restartCount:i.restartCount,resources:{memoryBytes:i.memoryBytes}}],networks:[],mounts:a,capabilities:us(m,a.length?"This systemd runtime does not support redeploy or replica scaling through the scoped explorer":"File transfer requires a provider-reported service working directory; redeploy and scaling are unavailable"),config:oo({fragmentPath:i.fragmentPath,workingDirectory:i.workingDirectory,user:i.user,environment:i.environment,enabled:i.enabled}),discoveredAt:n.toISOString(),sourceId:r}})}class wl{read;id;provider="systemd";constructor(e,t="systemd:local"){this.read=e;this.id=t}async discover(e){return bC(yC(await this.read(e)),e,this.id)}}function SC(e,t){if(!e.success)throw Error(e.error||e.perInstance?.[0]?.error||`${t} discovery failed`);return e.perInstance?.[0]?.output??""}function vC(){return["set -uo pipefail",'command -v systemctl >/dev/null 2>&1 || { echo "systemctl is unavailable" >&2; exit 127; }',"systemctl list-units --type=service --all --plain --no-legend 2>/dev/null | awk '{print $1}' | while IFS= read -r unit; do",' [ -n "$unit" ] || continue',' clean() { printf "%s" "$1" | tr "\\t\\r\\n" " "; }',' load=$(systemctl show "$unit" -p LoadState --value 2>/dev/null || true)',' active=$(systemctl show "$unit" -p ActiveState --value 2>/dev/null || true)',' sub=$(systemctl show "$unit" -p SubState --value 2>/dev/null || true)',' description=$(systemctl show "$unit" -p Description --value 2>/dev/null || true)',' enabled=$(systemctl is-enabled "$unit" 2>/dev/null || true)',' pid=$(systemctl show "$unit" -p MainPID --value 2>/dev/null || true)',' memory=$(systemctl show "$unit" -p MemoryCurrent --value 2>/dev/null || true)',' restarts=$(systemctl show "$unit" -p NRestarts --value 2>/dev/null || true)',' since=$(systemctl show "$unit" -p ActiveEnterTimestamp --value 2>/dev/null || true)',' fragment=$(systemctl show "$unit" -p FragmentPath --value 2>/dev/null || true)',' working=$(systemctl show "$unit" -p WorkingDirectory --value 2>/dev/null || true)',' user=$(systemctl show "$unit" -p User --value 2>/dev/null || true)',' printf "TSCLOUD_SYSTEMD\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n" "$(clean "$unit")" "$(clean "$load")" "$(clean "$active")" "$(clean "$sub")" "$(clean "$description")" "$(clean "$enabled")" "$(clean "$pid")" "$(clean "$memory")" "$(clean "$restarts")" "$(clean "$since")" "$(clean "$fragment")" "$(clean "$working")" "$(clean "$user")"',"done"]}function wC(){return["set -uo pipefail",'if ! command -v docker >/dev/null 2>&1; then echo "[]"; exit 0; fi',"ids=$(docker ps -aq)",'if [ -z "$ids" ]; then echo "[]"; else docker inspect $ids; fi']}function uh(e,t,r,n,i){let o=`${e}:${r.id}`,s=async()=>SC(await t.runRemoteDeploy({targets:[r],commands:e==="systemd"?vC():wC(),timeoutSeconds:30,comment:`ts-cloud runtime discovery:${e}`,tags:{Project:n.project.slug,Environment:i,Role:"app"}}),o);return e==="systemd"?new wl(s,o):new vl(s,o)}async function td(e,t=100){let r=[],n;for(let i=0;i<t;i++){let o=await e(n);if(r.push(...o.items),!o.nextToken)return r;n=o.nextToken}throw Error(`Provider pagination exceeded ${t} pages`)}class lh{client;prefix;id="ecs:aws";provider="ecs";constructor(e,t){this.client=e;this.prefix=t}async discover(e){let t=await td(async(o)=>{let s=await this.client.listClusters({nextToken:o,maxResults:100});return{items:s.clusterArns??[],nextToken:s.nextToken}}),r=[],n=[],i=[];for(let o of t){let s=(await td(async(c)=>{let l=await this.client.listServices(o,{nextToken:c,maxResults:100});return{items:l.serviceArns??[],nextToken:l.nextToken}})).filter((c)=>c.split("/").at(-1)?.startsWith(this.prefix));for(let c=0;c<s.length;c+=10){let l=await this.client.describeServices({cluster:o,services:s.slice(c,c+10)});r.push(...l.services??[])}for(let c of r.filter((l)=>l.clusterArn===o||!l.clusterArn)){let l=await td(async(a)=>{let m=await this.client.listTasks(o,c.serviceName,{nextToken:a,maxResults:100});return{items:m.taskArns??[],nextToken:m.nextToken}});for(let a=0;a<l.length;a+=100){let m=await this.client.describeTasks(o,l.slice(a,a+100));n.push(...m.tasks??[])}}}if(this.client.describeTaskDefinition)for(let o of[...new Set(r.map((s)=>s.taskDefinition).filter((s)=>!!s))]){let s=await this.client.describeTaskDefinition(o);if(s.taskDefinition)i.push(s.taskDefinition)}return ch(r,n,e,this.id,i)}}class ph{client;prefix;id="lambda:aws";provider="lambda";constructor(e,t){this.client=e;this.prefix=t}async discover(e){let t=(await td(async(r)=>{let n=await this.client.listFunctions({Marker:r,MaxItems:50});return{items:n.Functions??[],nextToken:n.NextMarker}})).filter((r)=>r.FunctionName?.startsWith(this.prefix));return dh(t,e,this.id)}}async function IC(e,t,r={}){let n=[],i=V(e),o=U(e),s=e.aws?.profile,c=e.aws?.region??e.project.region??"us-east-1",l=`${e.project.slug}-${t}`;if(i!=="serverless"){let a=r.driver??x({config:e}),m=await a.findComputeTargets({slug:e.project.slug,environment:t,role:"app"});for(let E of m)n.push(uh("systemd",a,E,e,t)),n.push(uh("docker",a,E,e,t))}if(o==="aws")n.push(new lh(r.ecs??new It(c,s),l)),n.push(new ph(r.lambda??new R(c,s),l));return n}async function Si(e,t,r={}){let n={project:e.project.slug,environment:t};try{return await nh(await IC(e,t,r),n)}catch(i){return{generatedAt:new Date().toISOString(),workloads:[],sources:[{id:"runtime:bootstrap",provider:U(e)==="aws"?"ecs":"systemd",status:"error",discoveredAt:new Date().toISOString(),staleAfterSeconds:60,itemCount:0,message:String(i?.message??i).slice(0,500)}],degraded:!0}}}var gh=65536,Da=49152,nd=/^[A-Za-z0-9_.@:-]+\.service$/,id=/^[a-fA-F0-9]{12,128}$/,CC=["/boot","/dev","/etc","/proc","/root","/run","/sys","/var/run"];function Qs(e){let t=Buffer.from(e);return t.byteLength<=gh?e:`${t.subarray(0,gh-24).toString("utf8")}
|
|
121
|
+
[output truncated]`}function rd(e){return{success:!1,instanceCount:0,perInstance:[],error:e instanceof Error?e.message:String(e)}}function li(e){return`'${e.replaceAll("'",`'"'"'`)}'`}function EC(e,t){return Number.isFinite(e)?Math.min(1e4,Math.max(0,Math.floor(e))):t}function TC(e){let t=e.config,r=typeof t.clusterArn==="string"?t.clusterArn:void 0,n=e.links.providerId||e.name;return r&&n?{cluster:r,service:n}:void 0}function AC(e,t){return e.find((r)=>r.id===t.links.server)??(e.length===1?e[0]:void 0)}function kC(e,t){if(e.provider==="systemd"){let r=e.links.providerId;if(!r||!nd.test(r)||!["start","stop","restart"].includes(t))return;return[`systemctl ${t} ${r}`,`systemctl is-active ${r} 2>/dev/null || true`]}if(e.provider==="docker"){let r=e.links.providerId;if(!r||!id.test(r)||!["start","stop","restart"].includes(t))return;return[`docker ${t} ${r}`,`docker inspect --format '{{.State.Status}}' ${r}`]}return}function RC(e,t){if(!t.startsWith("/")||t.includes("\x00"))return{ok:!1,error:"An absolute path is required."};let r=[];for(let c of t.split("/")){if(!c||c===".")continue;if(c===".."){if(!r.length)return{ok:!1,error:"Path traversal is not allowed."};r.pop()}else r.push(c)}let n=`/${r.join("/")}`;if(CC.some((c)=>n===c||n.startsWith(`${c}/`)))return{ok:!1,error:"Sensitive host paths are not available through runtime file access."};let i=e.links.project?.replace(/[^A-Za-z0-9_-]/g,""),o=e.links.service?.replace(/[^A-Za-z0-9_-]/g,"");if(![...i&&o?[`/var/www/${i}/${o}`,`/srv/${i}/${o}`]:[],...e.mounts.map((c)=>c.target).filter((c)=>c.startsWith("/"))].some((c)=>n===c||n.startsWith(`${c.replace(/\/$/,"")}/`)))return{ok:!1,error:"Path is outside this service’s owned roots."};return{ok:!0,path:n}}function PC(e,t){let r=e.links.project?.replace(/[^A-Za-z0-9_-]/g,""),n=e.links.service?.replace(/[^A-Za-z0-9_-]/g,"");return[...r&&n?[`/var/www/${r}/${n}`,`/srv/${r}/${n}`]:[],...e.mounts.map((i)=>i.target).filter((i)=>i.startsWith("/"))].sort((i,o)=>o.length-i.length).find((i)=>t===i||t.startsWith(`${i.replace(/\/$/,"")}/`))}var mh={process:["ps","-eo","pid,ppid,user,%cpu,%mem,etime,command","--sort=-%cpu"],sockets:["ss","-lntup"],filesystem:["df","-h"]};class ge{config;environment;dependencies;region;profile;constructor(e,t,r={}){this.config=e;this.environment=t;this.dependencies=r;this.region=e.aws?.region??e.project.region??"us-east-1",this.profile=e.aws?.profile}async inventory(){return this.dependencies.inventory?.()??Si(this.config,this.environment,{driver:this.dependencies.driver})}async workload(e){return(await this.inventory()).workloads.find((t)=>t.id===e)}async remote(e,t,r,n){let i=this.dependencies.driver??x({config:this.config}),o=await i.findComputeTargets({slug:this.config.project.slug,environment:this.environment,role:"app"}),s=AC(o,e);if(!s)throw Error("The workload server is no longer reachable in this scope.");return i.runRemoteDeploy({targets:[s],commands:t,timeoutSeconds:r,comment:n,tags:{Project:this.config.project.slug,Environment:this.environment,Role:"app"}})}async run(e){let t=await this.workload(e.workloadId),r={workloadId:e.workloadId,action:e.action};if(!t)return{...r,ok:!1,error:"Workload was not found in the current project and environment."};let n=t.capabilities[e.action];if(!n.supported)return{...r,ok:!1,error:n.reason??`${e.action} is unsupported for ${t.provider}.`};if(n.requiresConfirmation&&e.confirm!==t.name)return{...r,ok:!1,error:`Type "${t.name}" to ${e.action} this workload.`};if(n.requiresRecentAuth&&!e.recentAuth)return{...r,ok:!1,error:"Sign in again before using elevated runtime access."};if(e.action==="inspect")return{...r,ok:!0,workload:t};if(t.provider==="systemd"||t.provider==="docker"){let i=kC(t,e.action);if(!i)return{...r,ok:!1,error:`${e.action} is not implemented for ${t.provider}.`};let o=await this.remote(t,["set -uo pipefail",...i],60,`ts-cloud runtime:${e.action}`).catch(rd);return{...r,ok:o.success,command:i[0],stdout:Qs(o.perInstance?.[0]?.output??""),stderr:Qs(o.perInstance?.[0]?.error??o.error??""),error:o.success?void 0:o.error??"Runtime operation failed."}}if(t.provider==="ecs"){let i=TC(t);if(!i)return{...r,ok:!1,error:"ECS cluster or service identity is unavailable."};let o=this.dependencies.ecs??new It(this.region,this.profile);if(e.action==="scale"){let s=EC(e.replicas,t.desiredReplicas??1);return await o.scaleService(i.cluster,i.service,s),{...r,ok:!0,command:`ecs scale ${t.name} ${s}`}}if(e.action==="start"||e.action==="stop"){let s=e.action==="stop"?0:Math.max(1,t.desiredReplicas??1);return await o.scaleService(i.cluster,i.service,s),{...r,ok:!0,command:`ecs scale ${t.name} ${s}`}}if(e.action==="restart"||e.action==="redeploy")return await o.forceNewDeployment(i.cluster,i.service),{...r,ok:!0,command:`ecs redeploy ${t.name}`}}return{...r,ok:!1,error:`${e.action} is not implemented for ${t.provider}.`}}async exec(e){let t={workloadId:e.workloadId,preset:e.preset},r=await this.workload(e.workloadId);if(!r)return{...t,ok:!1,error:"Workload was not found in the current project and environment."};if(process.env.TS_CLOUD_RUNTIME_EXEC==="0")return{...t,ok:!1,error:"Runtime exec is disabled by TS_CLOUD_RUNTIME_EXEC."};if(!r.capabilities.exec.supported)return{...t,ok:!1,error:r.capabilities.exec.reason??"Exec is unsupported for this workload."};if(e.confirm!==r.name)return{...t,ok:!1,error:`Type "${r.name}" to open exec access.`};if(!e.recentAuth)return{...t,ok:!1,error:"Sign in again before using elevated runtime access."};let n=e.preset&&mh[e.preset];if(!n&&!e.command?.trim())return{...t,ok:!1,error:"Choose a diagnostic preset or provide a command."};if(e.command&&r.provider!=="docker")return{...t,ok:!1,error:"Free-form exec is restricted to isolated containers; use a diagnostic preset for system services."};let i=r.links.providerId??"",o;if(r.provider==="docker"&&id.test(i)){let c=e.command?.trim()||n.map(li).join(" ");o=`docker exec ${i} sh -lc ${li(c)}`}else if(r.provider==="systemd"&&nd.test(i)&&e.preset)o=e.preset==="process"?`systemctl status ${i} --no-pager --full`:mh[e.preset].map(li).join(" ");if(!o)return{...t,ok:!1,error:"Exec target identity is invalid or unsupported."};let s=await this.remote(r,["set -uo pipefail",o],60,"ts-cloud runtime:exec").catch(rd);return{...t,ok:s.success,command:o,stdout:Qs(s.perInstance?.[0]?.output??""),stderr:Qs(s.perInstance?.[0]?.error??s.error??""),error:s.success?void 0:s.error??"Exec command failed."}}async readFile(e){let t={workloadId:e.workloadId,path:e.path},r=await this.fileTarget(e);if("error"in r)return{...t,ok:!1,error:r.error};let{workload:n,path:i,root:o,providerId:s}=r,l=`sh -c ${li('resolved=$(realpath -m "$1"); root=$(realpath -m "$3"); case "$resolved" in "$root"|"$root"/*) ;; *) exit 73;; esac; test -f "$resolved"; size=$(wc -c < "$resolved"); printf "__TSCLOUD_SIZE__=%s\\n" "$size"; head -c "$2" "$resolved" | base64')} sh ${li(i)} ${Da} ${li(o)}`,a=n.provider==="docker"?`docker exec ${s} ${l}`:l,m=await this.remote(n,[a],30,"ts-cloud runtime:file-read").catch(rd);if(!m.success)return{...t,ok:!1,error:m.error??m.perInstance?.[0]?.error??"File read failed."};let E=m.perInstance?.[0]?.output??"",k=/__TSCLOUD_SIZE__=(\d+)\r?\n/.exec(E);if(!k)return{...t,ok:!1,error:"The remote file response was invalid."};let O=Number(k[1]),q=E.slice((k.index??0)+k[0].length).replace(/\s+/g,"");if(Buffer.from(q,"base64").byteLength>Da)return{...t,ok:!1,error:"The remote file exceeded the transfer limit."};return{...t,ok:!0,contentBase64:q,size:O,truncated:O>Da}}async writeFile(e){let t={workloadId:e.workloadId,path:e.path},r=await this.fileTarget(e);if("error"in r)return{...t,ok:!1,error:r.error};if(!/^[A-Za-z0-9+/]*={0,2}$/.test(e.contentBase64))return{...t,ok:!1,error:"File content must be valid base64."};let n=Buffer.from(e.contentBase64,"base64");if(n.toString("base64")!==e.contentBase64)return{...t,ok:!1,error:"File content must be canonical base64."};if(n.byteLength>Da)return{...t,ok:!1,error:`File uploads are limited to ${Da} bytes.`};let{workload:i,path:o,root:s,providerId:c}=r,a=`sh -c ${li('resolved=$(realpath -m "$1"); root=$(realpath -m "$2"); case "$resolved" in "$root"|"$root"/*) ;; *) exit 73;; esac; mkdir -p "$(dirname "$resolved")"; tmp="$resolved.ts-cloud-$$"; base64 -d > "$tmp"; chmod 600 "$tmp"; mv "$tmp" "$resolved"')} sh ${li(o)} ${li(s)}`,m=i.provider==="docker"?`printf %s ${li(e.contentBase64)} | docker exec -i ${c} ${a}`:`printf %s ${li(e.contentBase64)} | ${a}`,E=await this.remote(i,[m],30,"ts-cloud runtime:file-write").catch(rd);return{...t,ok:E.success,size:n.byteLength,truncated:!1,error:E.success?void 0:E.error??E.perInstance?.[0]?.error??"File write failed."}}async fileTarget(e){let t=await this.workload(e.workloadId);if(!t)return{error:"Workload was not found in the current project and environment."};if(process.env.TS_CLOUD_RUNTIME_FILE_ACCESS==="0")return{error:"Runtime file access is disabled by TS_CLOUD_RUNTIME_FILE_ACCESS."};if(!t.capabilities.files.supported)return{error:t.capabilities.files.reason??"File access is unsupported for this workload."};if(e.confirm!==t.name)return{error:`Type "${t.name}" to access workload files.`};if(!e.recentAuth)return{error:"Sign in again before using elevated runtime access."};let r=RC(t,e.path);if(!r.ok)return{error:r.error};let n=PC(t,r.path),i=t.links.providerId??"";if(!n||t.provider==="systemd"&&!nd.test(i)||t.provider==="docker"&&!id.test(i))return{error:"File target identity is invalid or unsupported."};return{workload:t,path:r.path,root:n,providerId:i}}async logs(e,t={}){let r=await this.workload(e);if(!r)throw Error("Workload was not found in the current project and environment.");if(!r.capabilities.logs.supported)throw Error(r.capabilities.logs.reason??"Logs are unsupported for this workload.");let n=Math.min(1000,Math.max(1,Math.floor(t.limit??200)));if(r.provider==="lambda"||r.provider==="ecs"){let m=this.dependencies.logs??new ne(this.region,this.profile),E=r.config.logGroups,k=r.provider==="lambda"?`/aws/lambda/${r.name}`:Array.isArray(E)&&typeof E[0]==="string"?E[0]:void 0;if(!k)throw Error("The ECS task definition does not declare an awslogs group.");let O=await m.filterLogEvents({logGroupName:k,startTime:t.since?.getTime(),limit:n}),q=(O.events??[]).slice(0,n).map((G)=>({timestamp:G.timestamp==null?void 0:new Date(G.timestamp).toISOString(),message:Qs(String(G.message??""))}));return{workloadId:e,provider:r.provider,lines:q,nextCursor:O.nextToken,truncated:(O.events?.length??0)>=n}}let i=r.links.providerId??"",o=t.since&&Number.isFinite(t.since.getTime())?t.since:void 0,s=r.provider==="systemd"&&nd.test(i)?`journalctl -u ${i} --no-pager -n ${n} -o short-iso${o?` --since ${li(o.toISOString())}`:""}`:r.provider==="docker"&&id.test(i)?`docker logs --timestamps --tail ${n}${o?` --since ${Math.floor(o.getTime()/1000)}`:""} ${i} 2>&1`:void 0;if(!s)throw Error("Log target identity is invalid.");let c=await this.remote(r,[s],30,"ts-cloud runtime:logs");if(!c.success)throw Error(c.error??c.perInstance?.[0]?.error??"Log read failed.");let l=Qs(c.perInstance?.[0]?.output??""),a=l.split(`
|
|
122
|
+
`).filter(Boolean).slice(-n).map((m)=>{let E=/^(\d{4}-\d{2}-\d{2}T\S+)\s+(.*)$/.exec(m);return{timestamp:E?.[1],message:E?.[2]??m}});return{workloadId:e,provider:r.provider,lines:a,truncated:l.includes("[output truncated]")||a.length>=n}}}import{randomUUID as xC}from"node:crypto";class Il{records=new Map;maxBufferBytes;ttlMs;now;constructor(e={}){this.maxBufferBytes=Math.max(1024,e.maxBufferBytes??262144),this.ttlMs=Math.max(1000,e.ttlMs??900000),this.now=e.now??(()=>new Date)}create(e,t){this.sweep();let r=this.now().toISOString(),n={id:xC(),workloadId:t,kind:e,state:"open",chunks:[],cursor:0,droppedBytes:0,bufferedBytes:0,createdAt:r,updatedAt:r,abort:new AbortController,listeners:new Set};return this.records.set(n.id,n),this.snapshot(n,0)}signal(e){return this.records.get(e)?.abort.signal}append(e,t,r="stdout"){let n=this.records.get(e);if(!n||n.state!=="open"||!t)return n?this.snapshot(n,n.cursor):void 0;let i=Buffer.from(t),o=i.byteLength>this.maxBufferBytes?i.subarray(i.byteLength-this.maxBufferBytes).toString("utf8"):t,s={cursor:++n.cursor,stream:r,data:o,at:this.now().toISOString()};n.chunks.push(s),n.bufferedBytes+=Buffer.byteLength(o),n.updatedAt=s.at;while(n.bufferedBytes>this.maxBufferBytes&&n.chunks.length>1){let c=n.chunks.shift(),l=Buffer.byteLength(c.data);n.bufferedBytes-=l,n.droppedBytes+=l}return this.publish(n),this.snapshot(n,s.cursor-1)}read(e,t,r=0){let n=this.records.get(e);if(!n||n.workloadId!==t)return;return n.updatedAt=this.now().toISOString(),this.snapshot(n,Math.max(0,Math.floor(r)))}close(e,t="complete",r){let n=this.records.get(e);if(!n||n.state!=="open")return n?this.snapshot(n,n.cursor):void 0;if(n.state=t,n.error=r,n.updatedAt=this.now().toISOString(),t==="cancelled")n.abort.abort();return this.publish(n),this.snapshot(n,n.cursor)}cancel(e,t){let r=this.records.get(e);if(!r||r.workloadId!==t)return;return this.close(e,"cancelled")}subscribe(e,t,r){let n=this.records.get(e);if(!n||n.workloadId!==t)return;return n.listeners.add(r),()=>n.listeners.delete(r)}sweep(){let e=this.now().getTime()-this.ttlMs,t=0;for(let[r,n]of this.records){if(new Date(n.updatedAt).getTime()>e)continue;n.abort.abort(),this.records.delete(r),t++}return t}clear(){for(let e of this.records.values())e.abort.abort();this.records.clear()}snapshot(e,t){let r=e.chunks[0]?.cursor??e.cursor+1,n=t>0&&t<r-1;return{id:e.id,workloadId:e.workloadId,kind:e.kind,state:e.state,chunks:e.chunks.filter((i)=>n||i.cursor>t),cursor:e.cursor,reset:n,droppedBytes:e.droppedBytes,createdAt:e.createdAt,updatedAt:e.updatedAt,error:e.error}}publish(e){let t=this.snapshot(e,0);for(let r of e.listeners)r(t)}}import{createHash as DC}from"node:crypto";var Al={info:0,low:1,medium:2,high:3,critical:4},kl={record:0,warn:1,block:2},fh=new Set(["skipped","unavailable","unsupported","stale"]);function Ut(e){return typeof e==="string"?e:void 0}function Oo(e,t){try{return JSON.parse(String(e))}catch{return t}}function vi(e){return JSON.stringify(h(e))}function OC(e){if(!e)return;return String(h(e,2000))}function Cl(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:Ut(e.project_id),environmentId:Ut(e.environment_id),resourceId:Ut(e.resource_id),releaseId:Ut(e.release_id),scannerId:String(e.scanner_id),scannerVersion:String(e.scanner_version),status:String(e.status),error:Ut(e.error),metadata:Oo(e.metadata,{}),findingsCount:Number(e.findings_count),startedAt:String(e.started_at),completedAt:String(e.completed_at),durationMs:Number(e.duration_ms)}}function hh(e){return{id:String(e.id),fingerprint:String(e.fingerprint),organizationId:String(e.organization_id),projectId:Ut(e.project_id),environmentId:Ut(e.environment_id),resourceId:Ut(e.resource_id),releaseId:Ut(e.release_id),scanRunId:String(e.scan_run_id),scannerId:String(e.scanner_id),scannerVersion:String(e.scanner_version),ruleId:String(e.rule_id),severity:String(e.severity),title:String(e.title),description:String(e.description),evidence:Oo(e.evidence,{}),remediation:Ut(e.remediation),subject:String(e.subject),status:String(e.status),ownerActorId:Ut(e.owner_actor_id),recurrenceCount:Number(e.recurrence_count),firstSeenAt:String(e.first_seen_at),lastSeenAt:String(e.last_seen_at),resolvedAt:Ut(e.resolved_at),updatedAt:String(e.updated_at)}}function El(e){return{id:String(e.id),organizationId:String(e.organization_id),environmentId:Ut(e.environment_id),name:String(e.name),rules:Oo(e.rules,[]),requiredScanners:Oo(e.required_scanners,[]),scannerFailMode:String(e.scanner_fail_mode),enabled:Number(e.enabled)===1,version:Number(e.version),createdByActorId:Ut(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function yh(e,t){let r=Ut(e.revoked_at),n=String(e.expires_at);return{id:String(e.id),findingId:String(e.finding_id),policyId:Ut(e.policy_id),reason:String(e.reason),referenceUrl:Ut(e.reference_url),createdByActorId:String(e.created_by_actor_id),expiresAt:n,revokedAt:r,state:r?"revoked":n<=t?"expired":"active",createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Tl(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:Ut(e.environment_id),releaseId:String(e.release_id),kind:String(e.kind),format:String(e.format),digest:String(e.digest),summary:Oo(e.summary,{}),content:Ut(e.content),sensitive:Number(e.sensitive)===1,createdAt:String(e.created_at)}}function bh(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:String(e.environment_id),operationId:Ut(e.operation_id),policyId:String(e.policy_id),policyVersion:Number(e.policy_version),outcome:String(e.outcome),scannerVersions:Oo(e.scanner_versions,{}),findingIds:Oo(e.finding_ids,[]),waiverIds:Oo(e.waiver_ids,[]),explanation:String(e.explanation),createdAt:String(e.created_at)}}function _C(e,t){let r=[e.trim().toLowerCase(),t.ruleId.trim().toLowerCase(),t.organizationId,t.projectId??"",t.environmentId??"",t.resourceId??"",t.releaseId??"",t.subject.trim().toLowerCase()].join("\x00");return DC("sha256").update(r).digest("hex")}function Sh(e){if(!e)return;let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")throw Error("Security references must use HTTP or HTTPS");return t.toString()}function vh(e){if(!e.length)throw Error("A security policy needs at least one rule");return e.map((t)=>{if(!(t.minimumSeverity in Al))throw Error(`Unknown security severity: ${t.minimumSeverity}`);if(!(t.action in kl))throw Error(`Unknown security policy action: ${t.action}`);return{minimumSeverity:t.minimumSeverity,action:t.action,...t.scannerId?{scannerId:t.scannerId.trim()}:{}}})}class Rt{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)}recordScan(e){if(!e.organizationId||!e.scannerId.trim()||!e.scannerVersion.trim())throw Error("Organization, scanner id, and scanner version are required");let t=e.completedAt??this.now(),r=e.startedAt??t,n=e.durationMs??Math.max(0,new Date(t).getTime()-new Date(r).getTime()),i=e.findings??[],o=this.idFn(),s=new Set,c=[];return this.controlPlane.transaction(()=>{this.run(`INSERT INTO security_scan_runs
|
|
123
|
+
(id, organization_id, project_id, environment_id, resource_id, release_id, scanner_id, scanner_version, status, error, metadata, findings_count, started_at, completed_at, duration_ms)
|
|
124
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[o,e.organizationId,e.projectId??null,e.environmentId??null,e.resourceId??null,e.releaseId??null,e.scannerId.trim(),e.scannerVersion.trim(),e.status,OC(e.error)??null,vi(e.metadata??{}),i.length,r,t,Math.max(0,Math.floor(n))]);for(let l of i){let a={...l,organizationId:e.organizationId,projectId:l.projectId??e.projectId,environmentId:l.environmentId??e.environmentId,resourceId:l.resourceId??e.resourceId,releaseId:l.releaseId??e.releaseId},m=a.fingerprint?.trim()||_C(e.scannerId,a);s.add(m);let E=this.controlPlane.database.query("SELECT * FROM security_findings WHERE fingerprint = ?").get(m),k=E?this.controlPlane.database.query("SELECT * FROM security_waivers WHERE finding_id = ? AND revoked_at IS NULL AND expires_at > ? ORDER BY expires_at DESC LIMIT 1").get(String(E.id),t):void 0;if(E){let O=String(E.status)==="resolved"?Number(E.recurrence_count)+1:Number(E.recurrence_count),q=k?"waived":String(E.status)==="acknowledged"?"acknowledged":"open";this.run(`UPDATE security_findings SET scan_run_id = ?, scanner_version = ?, severity = ?, title = ?, description = ?, evidence = ?, remediation = ?,
|
|
125
|
+
status = ?, recurrence_count = ?, last_seen_at = ?, resolved_at = NULL, updated_at = ? WHERE id = ?`,[o,e.scannerVersion,a.severity,a.title.trim(),a.description.trim(),vi(a.evidence??{}),a.remediation?.trim()||null,q,O,t,t,String(E.id)]),c.push(this.getFinding(String(E.id)))}else{let O=this.idFn();this.run(`INSERT INTO security_findings
|
|
126
|
+
(id, fingerprint, organization_id, project_id, environment_id, resource_id, release_id, scan_run_id, scanner_id, scanner_version, rule_id,
|
|
127
|
+
severity, title, description, evidence, remediation, subject, status, first_seen_at, last_seen_at, updated_at)
|
|
128
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'open', ?, ?, ?)`,[O,m,a.organizationId,a.projectId??null,a.environmentId??null,a.resourceId??null,a.releaseId??null,o,e.scannerId,e.scannerVersion,a.ruleId.trim(),a.severity,a.title.trim(),a.description.trim(),vi(a.evidence??{}),a.remediation?.trim()||null,a.subject.trim(),t,t,t]),c.push(this.getFinding(O))}}if(e.status==="passed"||e.status==="failed"){let l=this.controlPlane.database.query(`SELECT * FROM security_findings WHERE organization_id = ? AND scanner_id = ?
|
|
129
|
+
AND project_id IS ? AND environment_id IS ? AND resource_id IS ? AND release_id IS ? AND status != 'resolved'`).all(e.organizationId,e.scannerId,e.projectId??null,e.environmentId??null,e.resourceId??null,e.releaseId??null);for(let a of l){if(s.has(String(a.fingerprint)))continue;this.run("UPDATE security_findings SET status = 'resolved', resolved_at = ?, updated_at = ? WHERE id = ?",[t,t,String(a.id)]),this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,resourceId:e.resourceId,type:"security.finding.resolved",payload:{findingId:String(a.id),scannerId:e.scannerId,reason:"not-observed"}})}}this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,resourceId:e.resourceId,type:"security.scan.completed",level:e.status==="failed"||fh.has(e.status)?"warning":"info",payload:{scanRunId:o,scannerId:e.scannerId,scannerVersion:e.scannerVersion,status:e.status,findingsCount:i.length,durationMs:n}})}),{run:this.getScanRun(o),findings:c.map((l)=>this.getFinding(l.id))}}getScanRun(e){let t=this.controlPlane.database.query("SELECT * FROM security_scan_runs WHERE id = ?").get(e);return t?Cl(t):void 0}listScanRuns(e){return this.controlPlane.database.query("SELECT * FROM security_scan_runs WHERE organization_id = ? AND project_id IS ? AND environment_id IS ? ORDER BY completed_at DESC, id DESC LIMIT ?").all(e.organizationId,e.projectId??null,e.environmentId??null,Math.min(500,Math.max(1,e.limit??100))).map(Cl)}getFinding(e){let t=this.controlPlane.database.query("SELECT * FROM security_findings WHERE id = ?").get(e);return t?hh(t):void 0}listFindings(e){this.expireWaivers();let t=["organization_id = ?"],r=[e.organizationId];if(e.projectId)t.push("project_id = ?"),r.push(e.projectId);if(e.environmentId)t.push("environment_id = ?"),r.push(e.environmentId);if(e.status)t.push("status = ?"),r.push(e.status);if(e.severity)t.push("severity = ?"),r.push(e.severity);return r.push(Math.min(1000,Math.max(1,e.limit??250))),this.controlPlane.database.query(`SELECT * FROM security_findings WHERE ${t.join(" AND ")} ORDER BY CASE severity WHEN 'critical' THEN 4 WHEN 'high' THEN 3 WHEN 'medium' THEN 2 WHEN 'low' THEN 1 ELSE 0 END DESC, last_seen_at DESC LIMIT ?`).all(...r).map(hh)}assignFinding(e,t,r){let n=this.getFinding(e);if(!n)throw Error("Security finding was not found");if(t&&!this.controlPlane.getActor(t))throw Error("Finding owner was not found");return this.run("UPDATE security_findings SET owner_actor_id = ?, updated_at = ? WHERE id = ?",[t??null,this.now(),e]),this.controlPlane.appendEvent({organizationId:n.organizationId,projectId:n.projectId,resourceId:n.resourceId,actorId:r,type:"security.finding.assigned",payload:{findingId:e,ownerActorId:t??null}}),this.getFinding(e)}acknowledgeFinding(e,t){let r=this.getFinding(e);if(!r)throw Error("Security finding was not found");if(r.status==="resolved")throw Error("A resolved finding cannot be acknowledged");return this.run("UPDATE security_findings SET status = 'acknowledged', updated_at = ? WHERE id = ?",[this.now(),e]),this.controlPlane.appendEvent({organizationId:r.organizationId,projectId:r.projectId,resourceId:r.resourceId,actorId:t,type:"security.finding.acknowledged",payload:{findingId:e}}),this.getFinding(e)}addComment(e){let t=this.getFinding(e.findingId);if(!t)throw Error("Security finding was not found");let r=e.body.trim();if(r.length<2||r.length>4000)throw Error("Finding comments must contain 2-4,000 characters");let n=Sh(e.referenceUrl),i=this.idFn(),o=this.now();return this.run("INSERT INTO security_finding_comments (id, finding_id, actor_id, body, reference_url, created_at) VALUES (?, ?, ?, ?, ?, ?)",[i,e.findingId,e.actorId,r,n??null,o]),this.controlPlane.appendEvent({organizationId:t.organizationId,projectId:t.projectId,resourceId:t.resourceId,actorId:e.actorId,type:"security.finding.commented",payload:{findingId:e.findingId,commentId:i,referenceUrl:n??null}}),{id:i,findingId:e.findingId,actorId:e.actorId,body:r,referenceUrl:n,createdAt:o}}listComments(e){return this.controlPlane.database.query("SELECT * FROM security_finding_comments WHERE finding_id = ? ORDER BY created_at, id").all(e).map((t)=>({id:String(t.id),findingId:String(t.finding_id),actorId:String(t.actor_id),body:String(t.body),referenceUrl:Ut(t.reference_url),createdAt:String(t.created_at)}))}createWaiver(e){let t=this.getFinding(e.findingId);if(!t)throw Error("Security finding was not found");let r=e.reason.trim();if(r.length<8||r.length>1000)throw Error("A waiver reason must contain 8-1,000 characters");let n=this.now(),i=new Date(e.expiresAt);if(!Number.isFinite(i.getTime())||i.toISOString()<=n)throw Error("A waiver must have a future expiry");if(i.getTime()-new Date(n).getTime()>31536000000)throw Error("A waiver cannot last longer than one year");let o=e.policyId?this.getPolicy(e.policyId):void 0;if(e.policyId&&(!o||o.organizationId!==t.organizationId))throw Error("Waiver policy does not match the finding organization");let s=this.idFn(),c=Sh(e.referenceUrl);return this.controlPlane.transaction(()=>{this.run(`INSERT INTO security_waivers (id, finding_id, policy_id, reason, reference_url, created_by_actor_id, expires_at, created_at, updated_at)
|
|
130
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[s,t.id,e.policyId??null,r,c??null,e.actorId,i.toISOString(),n,n]),this.run("UPDATE security_findings SET status = 'waived', updated_at = ? WHERE id = ?",[n,t.id]),this.controlPlane.appendEvent({organizationId:t.organizationId,projectId:t.projectId,resourceId:t.resourceId,actorId:e.actorId,type:"security.waiver.created",level:"warning",payload:{waiverId:s,findingId:t.id,policyId:e.policyId??null,reason:r,expiresAt:i.toISOString(),referenceUrl:c??null}})}),this.getWaiver(s)}revokeWaiver(e,t){let r=this.getWaiver(e);if(!r)throw Error("Security waiver was not found");if(r.revokedAt)return r;let n=this.getFinding(r.findingId),i=this.now();return this.controlPlane.transaction(()=>{this.run("UPDATE security_waivers SET revoked_at = ?, updated_at = ? WHERE id = ?",[i,i,e]),this.run("UPDATE security_findings SET status = 'open', updated_at = ? WHERE id = ? AND status = 'waived'",[i,r.findingId]),this.controlPlane.appendEvent({organizationId:n.organizationId,projectId:n.projectId,resourceId:n.resourceId,actorId:t,type:"security.waiver.revoked",level:"warning",payload:{waiverId:e,findingId:r.findingId}})}),this.getWaiver(e)}getWaiver(e){let t=this.controlPlane.database.query("SELECT * FROM security_waivers WHERE id = ?").get(e);return t?yh(t,this.now()):void 0}listWaivers(e){return(e?this.controlPlane.database.query("SELECT * FROM security_waivers WHERE finding_id = ? ORDER BY created_at DESC").all(e):this.controlPlane.database.query("SELECT * FROM security_waivers ORDER BY created_at DESC").all()).map((r)=>yh(r,this.now()))}expireWaivers(){let e=this.now(),t=this.controlPlane.database.query(`SELECT w.id AS waiver_id, f.* FROM security_waivers w JOIN security_findings f ON f.id = w.finding_id
|
|
131
|
+
WHERE w.revoked_at IS NULL AND w.expires_at <= ? AND f.status = 'waived'`).all(e);for(let r of t)this.run("UPDATE security_findings SET status = 'open', updated_at = ? WHERE id = ?",[e,String(r.id)]),this.controlPlane.appendEvent({organizationId:String(r.organization_id),projectId:Ut(r.project_id),resourceId:Ut(r.resource_id),type:"security.waiver.expired",level:"warning",payload:{waiverId:String(r.waiver_id),findingId:String(r.id)}});return t.length}createPolicy(e){let t=e.name.trim();if(!t)throw Error("Security policy name is required");let r=vh(e.rules),n=this.idFn(),i=this.now(),o=[...new Set((e.requiredScanners??[]).map((s)=>s.trim()).filter(Boolean))].sort();return this.run(`INSERT INTO security_policies (id, organization_id, environment_id, name, rules, required_scanners, scanner_fail_mode, created_by_actor_id, created_at, updated_at)
|
|
132
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n,e.organizationId,e.environmentId??null,t,vi(r),vi(o),e.scannerFailMode,e.actorId??null,i,i]),this.controlPlane.appendEvent({organizationId:e.organizationId,actorId:e.actorId,type:"security.policy.created",payload:{policyId:n,environmentId:e.environmentId??null,scannerFailMode:e.scannerFailMode,requiredScanners:o,rules:h(r)}}),this.getPolicy(n)}updatePolicy(e,t,r){let n=this.getPolicy(e);if(!n||n.version!==t)throw Error(`Security policy ${e} changed since version ${t}`);let i=r.rules?vh(r.rules):n.rules,o=r.requiredScanners?[...new Set(r.requiredScanners.map((l)=>l.trim()).filter(Boolean))].sort():n.requiredScanners,s=this.now();if(this.controlPlane.database.run("UPDATE security_policies SET name = ?, rules = ?, required_scanners = ?, scanner_fail_mode = ?, enabled = ?, version = version + 1, updated_at = ? WHERE id = ? AND version = ?",[r.name?.trim()||n.name,vi(i),vi(o),r.scannerFailMode??n.scannerFailMode,r.enabled??n.enabled?1:0,s,e,t]).changes!==1)throw Error(`Security policy ${e} changed since version ${t}`);return this.controlPlane.appendEvent({organizationId:n.organizationId,actorId:r.actorId,type:"security.policy.updated",payload:{policyId:e,fromVersion:t,toVersion:t+1}}),this.getPolicy(e)}getPolicy(e){let t=this.controlPlane.database.query("SELECT * FROM security_policies WHERE id = ?").get(e);return t?El(t):void 0}listPolicies(e){return this.controlPlane.database.query("SELECT * FROM security_policies WHERE organization_id = ? ORDER BY environment_id, name").all(e).map(El)}evaluateGate(e){this.expireWaivers();let t=e.policyId?this.getPolicy(e.policyId):this.controlPlane.database.query(`SELECT * FROM security_policies WHERE organization_id = ? AND enabled = 1 AND (environment_id = ? OR environment_id IS NULL)
|
|
133
|
+
ORDER BY CASE WHEN environment_id = ? THEN 0 ELSE 1 END, updated_at DESC LIMIT 1`).get(e.organizationId,e.environmentId,e.environmentId),r=t&&"rules"in t&&Array.isArray(t.rules)?t:t?El(t):void 0;if(!r||!r.enabled)throw Error("No enabled security policy applies to this environment");let n=this.listFindings({organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,limit:1000}).filter((ze)=>ze.status!=="resolved"),i=new Map;for(let ze of n){let Vt=this.listWaivers(ze.id).find((ut)=>ut.state==="active"&&(!ut.policyId||ut.policyId===r.id));if(Vt)i.set(ze.id,Vt)}let o=(ze)=>r.rules.filter((Vt)=>(!Vt.scannerId||Vt.scannerId===ze.scannerId)&&Al[ze.severity]>=Al[Vt.minimumSeverity]).reduce((Vt,ut)=>kl[ut.action]>kl[Vt]?ut.action:Vt,"record"),s=n.filter((ze)=>!i.has(ze.id)&&o(ze)==="block"),c=n.filter((ze)=>!i.has(ze.id)&&o(ze)==="warn"),l=this.controlPlane.database.query(`SELECT run.* FROM security_scan_runs run
|
|
134
|
+
WHERE run.organization_id = ? AND run.project_id = ? AND run.environment_id = ?
|
|
135
|
+
AND run.id = (SELECT candidate.id FROM security_scan_runs candidate
|
|
136
|
+
WHERE candidate.organization_id = run.organization_id AND candidate.project_id = run.project_id
|
|
137
|
+
AND candidate.environment_id = run.environment_id AND candidate.scanner_id = run.scanner_id
|
|
138
|
+
ORDER BY candidate.completed_at DESC, candidate.rowid DESC LIMIT 1)`).all(e.organizationId,e.projectId,e.environmentId),a=e.staleAfterMs??86400000,m=this.nowFn().getTime(),E=l.map(Cl).map((ze)=>m-new Date(ze.completedAt).getTime()>a?{...ze,status:"stale"}:ze),k=new Set(E.map((ze)=>ze.scannerId)),O=r.requiredScanners.filter((ze)=>!k.has(ze)).map((ze)=>({id:`missing:${ze}`,organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,scannerId:ze,scannerVersion:"unavailable",status:"unavailable",metadata:{},findingsCount:0,startedAt:this.now(),completedAt:this.now(),durationMs:0})),q=[...E,...O],G=q.filter((ze)=>r.requiredScanners.includes(ze.scannerId)&&fh.has(ze.status)),Y=Object.fromEntries(q.map((ze)=>[ze.scannerId,ze.scannerVersion])),re=r.scannerFailMode==="closed"&&G.length>0,he=s.length||re?"block":c.length||G.length?"warn":"allow",ee=[];if(s.length)ee.push(`${s.length} finding${s.length===1?"":"s"} blocked by policy`);if(c.length)ee.push(`${c.length} warning${c.length===1?"":"s"} require review`);if(G.length)ee.push(`${G.length} scanner${G.length===1?"":"s"} ${r.scannerFailMode==="closed"?"failed closed":"failed open"}`);if(i.size)ee.push(`${i.size} active time-limited waiver${i.size===1?"":"s"}`);if(!ee.length)ee.push("All recorded checks satisfy policy");let Re=this.idFn(),at=this.now();return this.run(`INSERT INTO security_deploy_decisions
|
|
139
|
+
(id, organization_id, project_id, environment_id, operation_id, policy_id, policy_version, outcome, scanner_versions, finding_ids, waiver_ids, explanation, created_at)
|
|
140
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[Re,e.organizationId,e.projectId,e.environmentId,e.operationId??null,r.id,r.version,he,vi(Y),vi([...s,...c].map((ze)=>ze.id)),vi([...i.values()].map((ze)=>ze.id)),ee.join("; "),at]),this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,operationId:e.operationId,type:"security.deploy.decision",level:he==="block"?"error":he==="warn"?"warning":"info",payload:{decisionId:Re,outcome:he,policyId:r.id,policyVersion:r.version,scannerVersions:Y,blockerIds:s.map((ze)=>ze.id),waiverIds:[...i.values()].map((ze)=>ze.id),explanation:ee.join("; ")}}),this.getDecision(Re)}getDecision(e){let t=this.controlPlane.database.query("SELECT * FROM security_deploy_decisions WHERE id = ?").get(e);return t?bh(t):void 0}listDecisions(e,t=100){return this.controlPlane.database.query("SELECT * FROM security_deploy_decisions WHERE environment_id = ? ORDER BY created_at DESC LIMIT ?").all(e,Math.min(500,Math.max(1,t))).map(bh)}addReleaseArtifact(e){let t=this.controlPlane.database.query("SELECT * FROM release_security_artifacts WHERE release_id = ? AND kind = ? AND digest = ?").get(e.releaseId,e.kind,e.digest);if(t)return Tl(t);let r=this.idFn(),n=this.now();return this.run(`INSERT INTO release_security_artifacts
|
|
141
|
+
(id, organization_id, project_id, environment_id, release_id, kind, format, digest, summary, content, sensitive, created_at)
|
|
142
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r,e.organizationId,e.projectId,e.environmentId??null,e.releaseId,e.kind,e.format,e.digest,vi(e.summary),e.content??null,e.sensitive?1:0,n]),this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,type:"security.release_artifact.created",payload:{artifactId:r,releaseId:e.releaseId,kind:e.kind,format:e.format,digest:e.digest,sensitive:e.sensitive}}),Tl(this.controlPlane.database.query("SELECT * FROM release_security_artifacts WHERE id = ?").get(r))}listReleaseArtifacts(e,t=!1){return this.controlPlane.database.query("SELECT * FROM release_security_artifacts WHERE release_id = ? ORDER BY created_at, kind").all(e).map(Tl).map((r)=>r.sensitive&&!t?{...r,content:void 0}:r)}summary(e,t,r){let n=this.listFindings({organizationId:e,projectId:t,environmentId:r,limit:1000}),i=this.listScanRuns({organizationId:e,projectId:t,environmentId:r,limit:1000}),o={info:0,low:0,medium:0,high:0,critical:0};for(let c of n)if(c.status==="open"||c.status==="acknowledged")o[c.severity]++;let s={passed:0,failed:0,skipped:0,unavailable:0,unsupported:0,stale:0};for(let c of i)s[c.status]++;return{open:o,waived:n.filter((c)=>c.status==="waived").length,resolved:n.filter((c)=>c.status==="resolved").length,checks:s,lastScannedAt:i[0]?.completedAt}}exportPosture(e){let t=this.controlPlane.listProjects().filter((r)=>r.organizationId===e);return h({format:"ts-cloud-security-posture",version:1,exportedAt:this.now(),organizationId:e,policies:this.listPolicies(e),findings:this.listFindings({organizationId:e,limit:1000}),waivers:this.listWaivers().filter((r)=>this.getFinding(r.findingId)?.organizationId===e),scans:t.flatMap((r)=>this.listScanRuns({organizationId:e,projectId:r.id,limit:1000})),decisions:t.flatMap((r)=>this.controlPlane.listEnvironments(r.id).flatMap((n)=>this.listDecisions(n.id,1000)))})}}import{existsSync as NC,readdirSync as $C,readFileSync as MC,statSync as LC}from"node:fs";import{extname as BC,join as jC,relative as FC}from"node:path";var wh=[{name:"AWS Access Key ID",pattern:/(?:^|[^A-Z0-9])((AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16})(?:[^A-Z0-9]|$)/g,severity:"critical",description:"AWS Access Key ID detected"},{name:"AWS Secret Access Key",pattern:/(?:aws_secret_access_key|aws_secret_key|secret_access_key|secretAccessKey)['"]?\s*[=:]\s*['"]?([A-Za-z0-9/+=]{40})['"]?/gi,severity:"critical",description:"AWS Secret Access Key detected"},{name:"AWS Secret Key (Generic)",pattern:/(?:^|['"`:=\s])([A-Za-z0-9/+=]{40})(?:['"`\s]|$)/g,severity:"high",description:"Potential AWS Secret Key (40-char base64)"},{name:"Generic API Key",pattern:/(?:api[_-]?key|apikey|api[_-]?secret)\s*[=:]\s*['"]?([A-Za-z0-9_\-]{20,})['"]?/gi,severity:"high",description:"Generic API key detected"},{name:"RSA Private Key",pattern:/-----BEGIN RSA PRIVATE KEY-----/g,severity:"critical",description:"RSA private key detected"},{name:"OpenSSH Private Key",pattern:/-----BEGIN OPENSSH PRIVATE KEY-----/g,severity:"critical",description:"OpenSSH private key detected"},{name:"EC Private Key",pattern:/-----BEGIN EC PRIVATE KEY-----/g,severity:"critical",description:"EC private key detected"},{name:"PGP Private Key",pattern:/-----BEGIN PGP PRIVATE KEY BLOCK-----/g,severity:"critical",description:"PGP private key detected"},{name:"GitHub Token",pattern:/(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/g,severity:"critical",description:"GitHub personal access token detected"},{name:"GitHub OAuth",pattern:/github[_-]?oauth[_-]?token\s*[=:]\s*['"]?([A-Za-z0-9_]{40})['"]?/gi,severity:"critical",description:"GitHub OAuth token detected"},{name:"Slack Token",pattern:/xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,severity:"critical",description:"Slack token detected"},{name:"Slack Webhook",pattern:/https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]+/g,severity:"high",description:"Slack webhook URL detected"},{name:"Discord Webhook",pattern:/https:\/\/discord(?:app)?\.com\/api\/webhooks\/[0-9]+\/[A-Za-z0-9_-]+/g,severity:"high",description:"Discord webhook URL detected"},{name:"JWT Token",pattern:/eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*/g,severity:"high",description:"JWT token detected"},{name:"Google API Key",pattern:/AIza[0-9A-Za-z_-]{35}/g,severity:"critical",description:"Google API key detected"},{name:"Google OAuth ID",pattern:/[0-9]+-[A-Za-z0-9_]{32}\.apps\.googleusercontent\.com/g,severity:"high",description:"Google OAuth client ID detected"},{name:"Firebase API Key",pattern:/(?:firebase[_-]?api[_-]?key)\s*[=:]\s*['"]?([A-Za-z0-9_-]{39})['"]?/gi,severity:"critical",description:"Firebase API key detected"},{name:"Cloudflare API Token",pattern:/(?:cloudflare[_-]?api[_-]?token|cf[_-]?api[_-]?token)\s*[=:]\s*['"]?([A-Za-z0-9_-]{40})['"]?/gi,severity:"critical",description:"Cloudflare API token detected"},{name:"Azure Client Secret",pattern:/(?:azure[_-]?client[_-]?secret|client[_-]?secret)\s*[=:]\s*['"]?([A-Za-z0-9~._-]{34,})['"]?/gi,severity:"critical",description:"Azure client secret detected"},{name:"Heroku API Key",pattern:/(?:heroku[_-]?api[_-]?key)\s*[=:]\s*['"]?([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})['"]?/gi,severity:"critical",description:"Heroku API key detected"},{name:"Database Connection String",pattern:/(?:mysql|postgres|postgresql|mongodb|redis|mongodb\+srv):\/\/[^:]+:[^@]+@[^/\s]+/gi,severity:"critical",description:"Database connection string with credentials detected"},{name:"Database Password",pattern:/(?:db[_-]?password|database[_-]?password|mysql[_-]?password|postgres[_-]?password)\s*[=:]\s*['"]?([^'"\s]{8,})['"]?/gi,severity:"critical",description:"Database password detected"},{name:"Stripe API Key",pattern:/(?:sk|pk)_(?:test|live)_[0-9a-zA-Z]{24,}/g,severity:"critical",description:"Stripe API key detected"},{name:"PayPal Client ID",pattern:/(?:paypal[_-]?client[_-]?id)\s*[=:]\s*['"]?([A-Za-z0-9_-]{80})['"]?/gi,severity:"high",description:"PayPal client ID detected"},{name:"Square Access Token",pattern:/sq0[a-z]{3}-[0-9A-Za-z_-]{22,}/g,severity:"critical",description:"Square access token detected"},{name:"Twilio API Key",pattern:/SK[a-f0-9]{32}/g,severity:"critical",description:"Twilio API key detected"},{name:"SendGrid API Key",pattern:/SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}/g,severity:"critical",description:"SendGrid API key detected"},{name:"Mailgun API Key",pattern:/key-[0-9a-zA-Z]{32}/g,severity:"critical",description:"Mailgun API key detected"},{name:"Password in Code",pattern:/(?:password|passwd|pwd)\s*[=:]\s*['"]([^'"]{8,})['"](?!\s*[,\]])/gi,severity:"high",description:"Hardcoded password detected"},{name:"Secret/Token Assignment",pattern:/(?:secret|token|auth[_-]?token|access[_-]?token)\s*[=:]\s*['"]([A-Za-z0-9_\-/+=]{16,})['"](?!\s*[,\]])/gi,severity:"high",description:"Hardcoded secret or token detected"},{name:"NPM Token",pattern:/(?:npm[_-]?token)\s*[=:]\s*['"]?([A-Za-z0-9_-]{36})['"]?/gi,severity:"critical",description:"NPM token detected"},{name:"SSH Private Key Path Exposed",pattern:/~\/\.ssh\/id_[a-z]+|\/home\/[^/]+\/\.ssh\/id_[a-z]+/g,severity:"medium",description:"SSH private key path exposed"},{name:"Env Variable with Secret",pattern:/(?:process\.env\.)((?=[A-Z_]*(?:SECRET|KEY|TOKEN|PASSWORD|CREDENTIAL|AUTH))[A-Z_]+)\s*(?:===?\s*['"]([^'"]+)['"])?/g,severity:"medium",description:"Environment variable containing secret may be exposed"}],UC=[".js",".jsx",".ts",".tsx",".mjs",".cjs",".vue",".svelte",".html",".htm",".css",".scss",".less",".json",".yaml",".yml",".toml",".xml",".env",".config",".conf"],zC=["node_modules",".git",".svn",".hg","dist","build","coverage",".nyc_output","__pycache__",".pytest_cache","vendor",".idea",".vscode",".turbo",".next",".nuxt","framework.bak","pantry",".pantry","tests","test","__tests__","spec","__mocks__",".github",".gitlab",".circleci"],VC=["package-lock.json","yarn.lock","pnpm-lock.yaml","bun.lockb","bun.lock","*.min.js","*.min.css","*.map","*.d.ts","*.test.ts","*.test.js","*.spec.ts","*.spec.js",".env",".env.*"];class xr{patterns;excludeDirs;excludeFiles;maxFileSize;constructor(e){this.patterns=[...wh,...e?.customPatterns||[]],this.excludeDirs=[...zC,...e?.excludeDirs||[]],this.excludeFiles=[...VC,...e?.excludeFiles||[]],this.maxFileSize=e?.maxFileSize||1048576}async scan(e){let t=Date.now(),r=[],n=0,{directory:i,exclude:o=[],include:s,skipPatterns:c=[]}=e,l=e.failOnSeverity||"critical";if(!NC(i))throw Error(`Directory not found: ${i}`);let a=this.getFilesToScan(i,[...this.excludeDirs,...o],s);for(let q of a){let G=FC(i,q);if(this.shouldExcludeFile(G))continue;try{if(LC(q).size>this.maxFileSize)continue;let re=MC(q,"utf-8"),he=this.scanContent(re,G,c);r.push(...he),n++}catch{continue}}let m={critical:r.filter((q)=>q.pattern.severity==="critical").length,high:r.filter((q)=>q.pattern.severity==="high").length,medium:r.filter((q)=>q.pattern.severity==="medium").length,low:r.filter((q)=>q.pattern.severity==="low").length},E=["low","medium","high","critical"],k=E.indexOf(l),O=!0;for(let q=k;q<E.length;q++)if(m[E[q]]>0){O=!1;break}return{passed:O,findings:r,scannedFiles:n,duration:Date.now()-t,summary:m}}scanContent(e,t,r){let n=[],i=e.split(`
|
|
143
|
+
`);for(let o of this.patterns){if(r.includes(o.name))continue;o.pattern.lastIndex=0;let s;while((s=o.pattern.exec(e))!==null){let c=e.substring(0,s.index),l=c.split(`
|
|
144
|
+
`).length,a=c.lastIndexOf(`
|
|
145
|
+
`),m=s.index-a,E=i[l-1]||"";if(this.isLikelyPlaceholder(s[0],E))continue;let k=s[1]||s[0];if(o.name==="AWS Secret Key (Generic)"&&/^[a-f0-9]{40}$/i.test(k))continue;if(o.name==="AWS Secret Key (Generic)"&&!this.hasSecretCharacterDiversity(k))continue;if(o.name==="AWS Secret Key (Generic)"&&/^(?:Actions|Commands|Controllers|Handlers|Jobs|Listeners|Middleware|Models|Resources|Services)\//.test(k))continue;if(this.isLowEntropy(k))continue;n.push({file:t,line:l,column:m,match:this.maskSecret(s[0]),pattern:o,context:this.maskSecret(E.trim())})}}return n}isLikelyPlaceholder(e,t){let r=["example","placeholder","your_","YOUR_","xxx","XXX","***","test","TEST","dummy","DUMMY","fake","FAKE","sample","SAMPLE","<your","${","{{","process.env","import.meta.env","CHANGEME","TODO","FIXME"],n=e.toLowerCase(),i=t.toLowerCase();for(let s of r)if(n.includes(s.toLowerCase())||i.includes(s.toLowerCase()))return!0;let o=t.trim();if(o.startsWith("//")||o.startsWith("#")||o.startsWith("*")||o.startsWith("/*")){if(i.includes("example")||i.includes("format:")||i.includes("e.g."))return!0}return!1}isLowEntropy(e){if(e.length<8)return!1;if(new Set(e).size<8)return!0;if(/(.)\1{3,}/.test(e))return!0;return!1}hasSecretCharacterDiversity(e){let t=/[\d+=]/.test(e),r=[/[a-z]/.test(e),/[A-Z]/.test(e),/\d/.test(e),/[/+=]/.test(e)];return t&&r.filter(Boolean).length>=3}maskSecret(e){if(e.length<=8)return"*".repeat(e.length);let t=Math.min(4,Math.floor(e.length*0.2));return e.substring(0,t)+"*".repeat(e.length-t*2)+e.substring(e.length-t)}getFilesToScan(e,t,r){let n=[],i=r||UC,o=(s)=>{let c=$C(s,{withFileTypes:!0});for(let l of c){let a=jC(s,l.name);if(l.isDirectory()){if(!t.includes(l.name))o(a)}else if(l.isFile()){let m=BC(l.name).toLowerCase();if(i.includes(m)||l.name.startsWith(".env")||l.name.endsWith(".config"))n.push(a)}}};return o(e),n}shouldExcludeFile(e){let t=e.split("/").pop()||"";for(let r of this.excludeFiles)if(r.startsWith("*")){let n=r.substring(1);if(t.endsWith(n))return!0}else if(r.endsWith("*")){let n=r.substring(0,r.length-1);if(t.startsWith(n))return!0}else if(t===r)return!0;return!1}addPattern(e){this.patterns.push(e)}getPatterns(){return[...this.patterns]}}function qC(e,t){return{status:"unavailable",findings:[],error:`${e.id} exceeded its ${t}ms timeout`,metadata:{timeoutMs:t}}}class ps{posture;defaultTimeoutMs;nowFn;constructor(e,t={}){this.posture=e;this.defaultTimeoutMs=t.defaultTimeoutMs??60000,this.nowFn=t.now??(()=>new Date)}async run(e,t){let r=this.nowFn(),n=Math.max(100,e.timeoutMs??this.defaultTimeoutMs),i=new AbortController,o,s=new Promise((m)=>{o=setTimeout(()=>{i.abort(),m(qC(e,n))},n)}),c;try{c=await Promise.race([e.scan({...t,signal:i.signal}),s])}catch(m){c={status:"unavailable",findings:[],error:m instanceof Error?m.message:String(m)}}finally{if(o)clearTimeout(o)}let l=this.nowFn(),a={...t,scannerId:e.id,scannerVersion:e.version,status:c.status,findings:c.findings,metadata:c.metadata,error:c.error,startedAt:r.toISOString(),completedAt:l.toISOString(),durationMs:Math.max(0,l.getTime()-r.getTime())};return this.posture.recordScan(a)}async runAll(e,t){return Promise.all(e.map((r)=>this.run(r,t)))}}class Oa{scanner;id="source-secrets";version="1.0.0";timeoutMs=30000;constructor(e=new xr){this.scanner=e}async scan(e){if(!e.artifactRoot)return{status:"skipped",findings:[],error:"No artifact root was supplied"};let t=await this.scanner.scan({directory:e.artifactRoot,failOnSeverity:"critical"});return{status:t.passed?"passed":"failed",findings:t.findings.map((r)=>({...e,ruleId:r.pattern.name.toLowerCase().replace(/[^a-z0-9]+/g,"-"),severity:r.pattern.severity,title:r.pattern.name,description:r.pattern.description,subject:`${r.file}:${r.line}`,evidence:{file:r.file,line:r.line,column:r.column,match:r.match,context:r.context},remediation:"Remove the credential, rotate it at its issuer, and use a managed secret or environment reference."})),metadata:{scannedFiles:t.scannedFiles,summary:t.summary}}}}function JC(e){let t=e?.toLowerCase();return t==="critical"||t==="high"||t==="medium"||t==="low"?t:"info"}class Rl{id="trivy-image";version;timeoutMs;constructor(e={}){this.version=e.version??"local",this.timeoutMs=e.timeoutMs??120000,this.executable=e.executable??"trivy"}executable;async scan(e){if(!e.imageRef)return{status:"skipped",findings:[],error:"No image reference was supplied"};let t;try{t=Bun.spawn([this.executable,"image","--format","json","--quiet","--scanners","vuln",e.imageRef],{stdout:"pipe",stderr:"pipe",env:{PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",HOME:"/nonexistent",TRIVY_NO_PROGRESS:"true"}})}catch(l){return{status:"unsupported",findings:[],error:l instanceof Error?l.message:String(l)}}let r=()=>t.kill();e.signal.addEventListener("abort",r,{once:!0});let[n,i,o]=await Promise.all([t.exited,new Response(t.stdout).text(),new Response(t.stderr).text()]);if(e.signal.removeEventListener("abort",r),n!==0)return{status:/not found|enoent/i.test(o)?"unsupported":"unavailable",findings:[],error:o.slice(0,2000)||`Trivy exited with ${n}`};let s=JSON.parse(i),c=[];for(let l of s.Results??[])for(let a of l.Vulnerabilities??[]){let m=a.VulnerabilityID??"unknown-vulnerability";c.push({...e,ruleId:m,severity:JC(a.Severity),title:a.Title||m,description:a.Description||`${m} affects ${a.PkgName??"an image package"}.`,subject:`${e.imageRef}:${a.PkgName??"unknown"}:${a.InstalledVersion??"unknown"}`,evidence:{image:e.imageRef,target:l.Target??"",cve:m,package:a.PkgName??"",installedVersion:a.InstalledVersion??"",fixedVersion:a.FixedVersion??"",reference:a.PrimaryURL??""},remediation:a.FixedVersion?`Upgrade ${a.PkgName} to ${a.FixedVersion} or later.`:"Remove or replace the affected package and rescan the image."})}return{status:c.length?"failed":"passed",findings:c,metadata:{imageRef:e.imageRef,vulnerabilityCount:c.length,localOnly:!0}}}}import{createHash as WC,createVerify as v$}from"node:crypto";import{existsSync as HC,readFileSync as GC}from"node:fs";import{basename as KC,join as QC,resolve as Ih}from"node:path";function Na(e){return WC("sha256").update(e).digest("hex")}function YC(e){let t=[["dependencies","required"],["optionalDependencies","optional"],["devDependencies","excluded"],["peerDependencies","required"]],r=new Map;for(let[n,i]of t){let o=e[n];if(!o||typeof o!=="object"||Array.isArray(o))continue;for(let[s,c]of Object.entries(o)){let l=String(c).replace(/^[~^]/,""),a=`${s}@${l}`;if(!r.has(a))r.set(a,{type:"library",name:s,version:l,purl:`pkg:npm/${encodeURIComponent(s)}@${encodeURIComponent(l)}`,scope:i})}}return[...r.values()].sort((n,i)=>`${n.name}@${n.version}`.localeCompare(`${i.name}@${i.version}`))}function Ch(e,t={}){let r=QC(Ih(e),"package.json");if(!HC(r))throw Error(`Cannot generate an SBOM: ${r} was not found`);let n=GC(r,"utf8"),i=JSON.parse(n),o=String(i.name??KC(Ih(e))),s=String(i.version??"0.0.0"),c=Na(n);return{bomFormat:"CycloneDX",specVersion:"1.5",serialNumber:t.serial??`urn:uuid:${crypto.randomUUID()}`,version:1,metadata:{timestamp:(t.now??new Date).toISOString(),component:{type:"application",name:o,version:s,purl:`pkg:npm/${encodeURIComponent(o)}@${encodeURIComponent(s)}`,hashes:[{alg:"SHA-256",content:c}]},tools:[{vendor:"ts-cloud",name:"security-posture",version:"1.0.0"}]},components:YC(i)}}async function Eh(e,t={}){let r=Bun.spawn([t.executable??"syft",e,"-o","cyclonedx-json"],{stdout:"pipe",stderr:"pipe",env:{PATH:process.env.PATH??"/usr/local/bin:/usr/bin:/bin",HOME:"/nonexistent",SYFT_CHECK_FOR_APP_UPDATE:"false"}}),n=()=>r.kill();t.signal?.addEventListener("abort",n,{once:!0});let[i,o,s]=await Promise.all([r.exited,new Response(r.stdout).text(),new Response(r.stderr).text()]);if(t.signal?.removeEventListener("abort",n),i!==0)throw Error(s.slice(0,2000)||`Syft exited with ${i}`);return JSON.parse(o)}function Pl(e,t,r){let n=JSON.stringify(r);return e.addReleaseArtifact({...t,kind:"sbom",format:`cyclonedx-${r.specVersion}+json`,digest:`sha256:${Na(n)}`,summary:{component:r.metadata.component.name,version:r.metadata.component.version,components:r.components.length},content:n,sensitive:!0})}function Th(e,t,r){let n={total:r.length,critical:0,high:0,medium:0,low:0,info:0,fixable:0};for(let o of r){n[o.severity]++;let s=o.evidence;if(typeof s.fixedVersion==="string"&&s.fixedVersion)n.fixable++}let i=JSON.stringify({releaseId:t.releaseId,generatedAt:new Date().toISOString(),findings:r.map((o)=>({id:o.id,ruleId:o.ruleId,severity:o.severity,subject:o.subject,remediation:o.remediation}))});return e.addReleaseArtifact({...t,kind:"vulnerability_summary",format:"ts-cloud-vulnerability-summary+json",digest:`sha256:${Na(i)}`,summary:n,content:i,sensitive:!0})}function Ah(e){if(!e.artifact&&!e.artifactSha256)throw Error("Release provenance requires artifact content or a SHA-256 digest");return{_type:"https://in-toto.io/Statement/v1",subject:[{name:e.artifactName,digest:{sha256:e.artifactSha256?.replace(/^sha256:/,"")??Na(e.artifact)}}],predicateType:"https://slsa.dev/provenance/v1",predicate:{buildDefinition:{buildType:"https://ts-cloud.dev/build/v1",externalParameters:e.externalParameters??{},internalParameters:{},resolvedDependencies:e.resolvedDependencies??[]},runDetails:{builder:{id:"https://ts-cloud.dev/builders/local/v1"},metadata:{invocationId:e.invocationId,startedOn:e.startedAt,finishedOn:e.completedAt}}}}}function kh(e,t,r){let n=JSON.stringify(r);return e.addReleaseArtifact({...t,kind:"provenance",format:"in-toto+slsa-v1+json",digest:`sha256:${Na(n)}`,summary:{subjects:r.subject.length,builder:r.predicate.runDetails.builder.id,buildType:r.predicate.buildDefinition.buildType},content:n,sensitive:!0})}function ae(e,t){let r=e.environments.get(t);if(!r)throw Error(`Security scope for environment '${t}' was not found`);return{organizationId:e.organization.id,projectId:e.project.id,environmentId:r.id}}function _n(e,t){let r=new Rt(e.store),n=r.listPolicies(e.organization.id);for(let[i,o]of e.environments){if(n.some((c)=>c.environmentId===o.id))continue;let s=i==="production"||o.kind==="production";n.push(r.createPolicy({organizationId:e.organization.id,environmentId:o.id,name:s?"Production baseline":"Environment baseline",scannerFailMode:s?"closed":"open",requiredScanners:["source-secrets"],rules:s?[{minimumSeverity:"critical",action:"block"},{minimumSeverity:"high",action:"block"},{minimumSeverity:"medium",action:"warn"},{minimumSeverity:"low",action:"record"}]:[{minimumSeverity:"critical",action:"warn"},{minimumSeverity:"high",action:"warn"},{minimumSeverity:"low",action:"record"}],actorId:t}))}return n}function na(e,t,r,n={}){let i=r.findings.map((o)=>({...t,ruleId:o.pattern.name.toLowerCase().replace(/[^a-z0-9]+/g,"-"),severity:o.pattern.severity,title:o.pattern.name,description:o.pattern.description,subject:`${o.file}:${o.line}`,evidence:{file:o.file,line:o.line,column:o.column,match:o.match,context:o.context},remediation:"Remove and rotate the credential, then reference it through a managed secret or environment variable."}));return e.recordScan({...t,scannerId:"source-secrets",scannerVersion:n.scannerVersion??"1.0.0",status:n.skipped?"skipped":r.passed?"passed":"failed",findings:n.skipped?[]:i,metadata:{scannedFiles:r.scannedFiles,durationMs:r.duration,summary:r.summary},durationMs:r.duration,error:n.skipped?"The operator explicitly skipped source-secret scanning.":void 0})}function ia(e,t,r="The operator explicitly skipped source-secret scanning."){return e.recordScan({...t,scannerId:"source-secrets",scannerVersion:"1.0.0",status:"skipped",findings:[],error:r})}function XC(e,t){let r=[],n=t.security;if(n?.firewall&&!["active","configured","ok"].includes(String(n.firewall.status)))r.push({...e,ruleId:"host-firewall-disabled",severity:"high",title:"Host firewall is not active",description:String(n.firewall.summary??"The host firewall did not report an active configuration."),subject:"host:firewall",evidence:{status:String(n.firewall.status??"unknown"),rules:Array.isArray(n.firewall.rules)?n.firewall.rules.length:0},remediation:"Apply the declarative firewall policy and confirm only required listeners are public."});for(let i of n?.ports??[]){let o=String(i.listen??""),s=Number(o.match(/:(\d+)$/)?.[1]);if(i.exposure==="public"&&Number.isFinite(s)&&![22,80,443].includes(s))r.push({...e,ruleId:"unexpected-public-listener",severity:"medium",title:`Unexpected public listener on port ${s}`,description:`${String(i.processName??"A process")} is listening publicly outside the standard SSH/HTTP/HTTPS ports.`,subject:`host:port:${s}`,evidence:{protocol:String(i.proto??""),listen:o,process:String(i.processName??"")},remediation:"Bind the service to loopback/private networking or explicitly document and firewall the required public port."})}for(let i of n?.tlsCertificates??[]){let o=Number(i.daysRemaining);if(Number.isFinite(o)&&o<30)r.push({...e,ruleId:"tls-certificate-expiry",severity:o<14?"high":"medium",title:`TLS certificate expires in ${o} days`,description:`${String(i.domain??"A configured domain")} needs renewal.`,subject:`tls:${String(i.domain??"unknown")}`,evidence:{domain:String(i.domain??""),daysRemaining:o,expires:String(i.expires??"")},remediation:"Renew the certificate and verify automatic renewal can complete before expiry."})}for(let i of t.diagnostics??[]){if(i.status==="pass"||i.status==="ok")continue;r.push({...e,ruleId:`diagnostic-${String(i.name??"unknown").toLowerCase().replace(/[^a-z0-9]+/g,"-")}`,severity:i.status==="fail"?"high":"medium",title:String(i.name??"Host security check"),description:String(i.detail??"The host security diagnostic did not pass."),subject:`diagnostic:${String(i.name??"unknown")}`,evidence:{status:String(i.status??"unknown")},remediation:"Follow the diagnostic guidance, rerun the check, and confirm the finding resolves."})}return r}function od(e,t,r){let n=!!r.security||Array.isArray(r.diagnostics),i=n?XC(t,r):[];return e.recordScan({...t,scannerId:"host-posture",scannerVersion:"1.0.0",status:!n?"unavailable":i.length?"failed":"passed",findings:i,metadata:{source:"dashboard-live-probe",checks:Array.isArray(r.diagnostics)?r.diagnostics.length:0},error:n?void 0:"Live host posture data was unavailable; source and provider checks remain usable."})}function Yt(e,t){let r=e.evaluateGate({...t.scope,operationId:t.operationId}),n=e.listFindings({...t.scope,limit:1000}).filter((i)=>i.status!=="resolved");return{decision:r,summary:{desiredConfigHash:t.desiredConfigHash??null,securityImpact:{critical:n.filter((i)=>i.severity==="critical").length,high:n.filter((i)=>i.severity==="high").length,waived:n.filter((i)=>i.status==="waived").length,assigned:n.filter((i)=>!!i.ownerActorId).length},blockingFindingIds:r.findingIds,policy:{id:r.policyId,version:r.policyVersion},scannerVersions:r.scannerVersions}}}async function oa(e,t){let r=t.scanner??new Rl({timeoutMs:t.scannerTimeoutMs}),i=await new ps(e,{defaultTimeoutMs:t.scannerTimeoutMs??120000}).run(r,{...t.scope,releaseId:t.releaseId,imageRef:t.imageRef}),o={...t.scope,releaseId:t.releaseId};Th(e,o,i.findings);let s=t.generateImageSbom??Eh,c=new AbortController,l=Math.max(100,t.sbomTimeoutMs??120000),a,m=new Promise((O,q)=>{a=setTimeout(()=>{c.abort(),q(Error(`syft-sbom exceeded its ${l}ms timeout`))},l)}),E="unavailable";try{let O=await Promise.race([s(t.imageRef,{signal:c.signal}),m]);Pl(e,o,O),e.recordScan({...t.scope,releaseId:t.releaseId,scannerId:"syft-sbom",scannerVersion:"local",status:"passed",metadata:{imageRef:t.imageRef,format:`cyclonedx-${O.specVersion}+json`,components:O.components.length,localOnly:!0}}),E="image"}catch(O){let q=O instanceof Error?O.message:String(O);try{let G=Ch(t.artifactRoot);Pl(e,o,G),e.recordScan({...t.scope,releaseId:t.releaseId,scannerId:"syft-sbom",scannerVersion:"local",status:"unsupported",error:`Image inventory was unavailable; attached a package-manifest SBOM instead. ${q}`,metadata:{imageRef:t.imageRef,fallback:"package-manifest",components:G.components.length,localOnly:!0}}),E="manifest"}catch(G){e.recordScan({...t.scope,releaseId:t.releaseId,scannerId:"syft-sbom",scannerVersion:"local",status:"unavailable",error:`Image and manifest SBOM generation were unavailable. ${q}; ${G instanceof Error?G.message:String(G)}`,metadata:{imageRef:t.imageRef,localOnly:!0}})}}finally{if(a)clearTimeout(a)}let k=Ah({artifactName:t.imageRef,artifact:t.imageSha256?void 0:t.imageRef,artifactSha256:t.imageSha256,invocationId:t.invocationId,startedAt:t.startedAt,completedAt:t.completedAt??new Date().toISOString(),externalParameters:t.externalParameters??{imageRef:t.imageRef}});return kh(e,o,k),{scan:i,sbomSource:E}}import{randomBytes as Rh,scryptSync as Ph,timingSafeEqual as ZC}from"node:crypto";function _l(e,t){if(e.role==="admin")return[...t];return t.filter((r)=>!!e.sites?.[r])}var xl=32768,Dl=8,Ol=1,eE=32,tE=16;function No(e){let t=Rh(tE),r=Ph(e,t,eE,{N:xl,r:Dl,p:Ol,maxmem:268435456});return`scrypt$${xl}$${Dl}$${Ol}$${t.toString("base64url")}$${r.toString("base64url")}`}function Ti(e,t){try{let r=t.split("$");if(r.length!==6||r[0]!=="scrypt")return!1;let[,n,i,o,s,c]=r,l=Number(n),a=Number(i),m=Number(o);if(!Number.isFinite(l)||!Number.isFinite(a)||!Number.isFinite(m))return!1;let E=Buffer.from(s,"base64url"),k=Buffer.from(c,"base64url");if(E.length===0||k.length===0)return!1;let O=Ph(e,E,k.length,{N:l,r:a,p:m,maxmem:268435456});return ZC(O,k)}catch{return!1}}function xh(e){let[t,r,n,i]=e.split("$");return t!=="scrypt"||Number(r)!==xl||Number(n)!==Dl||Number(i)!==Ol}function Nl(){return Rh(18).toString("base64url")}import{createHash as rE}from"node:crypto";function nE(e){return rE("sha256").update(gs(e)).digest("hex")}function gs(e){if(Array.isArray(e))return`[${e.map((t)=>gs(t)).join(",")}]`;if(e&&typeof e==="object")return`{${Object.entries(e).filter(([,t])=>t!==void 0&&typeof t!=="function").sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>`${JSON.stringify(t)}:${gs(r)}`).join(",")}}`;return JSON.stringify(e)??"null"}function mr(e,t){let r=`dashboard:${t.username.toLowerCase()}`;return e.getActorByExternalId("user",r)??e.createActor({kind:"user",externalId:r,displayName:t.name??t.username,metadata:{source:"dashboard",role:t.role}})}function y(e,t){let r=new Tr({cwd:e}),n=nE(t),i=r.getProjectBySlug(t.project.slug),o=t.project.slug.length>=3?t.project.slug:`${t.project.slug}-org`,s=(i?.organizationId?r.getOrganization(i.organizationId):void 0)??r.getOrganizationBySlug(o)??r.createOrganization({id:i?.organizationId,slug:o,name:t.project.name}),c=i?i.name!==t.project.name||i.desiredConfigHash!==n||i.organizationId!==s.id?r.updateProject(i.id,i.version,{name:t.project.name,organizationId:s.id,desiredConfigHash:n}):i:r.createProject({organizationId:s.id,slug:t.project.slug,name:t.project.name,desiredConfigHash:n}),l=new Map;for(let[k,O]of Object.entries(t.environments??{})){let G=r.getEnvironmentBySlug(c.id,k)??r.createEnvironment({projectId:c.id,slug:k,name:k.replace(/(^|[-_])(\w)/g,(Re,at,ze)=>ze.toUpperCase()),kind:String(O?.type??k),region:O?.region??t.project.region,desiredState:h(O)});l.set(k,G);let Y=new Map(r.listResources(c.id,G.id).map((Re)=>[`${Re.kind}:${Re.slug}`,Re])),re=(Re,at,ze,Vt)=>{let ut=`${Re}:${at}`,Te=Y.get(ut),Qe=h(Vt);if(Te){if(Te.name!==ze||gs(Te.desiredState)!==gs(Qe))Y.set(ut,r.updateResource(Te.id,Te.version,{name:ze,desiredState:Qe}));return}let Tt=r.createResource({projectId:c.id,environmentId:G.id,kind:Re,slug:at,name:ze,provider:t.cloud?.provider,desiredState:Qe,metadata:{source:"cloud-config"}});Y.set(ut,Tt)};for(let[Re,at]of Object.entries(t.sites??{}))re("application",Re,Re,at);let he=O?.app;if(he)for(let Re of["http","queue","cli"])re("function",Re,`${Re.toUpperCase()} function`,{...h(he),function:Re});let ee=t.infrastructure;for(let[Re,at]of Object.entries(ee?.functions??{}))re("function",Re,Re,at);if(ee?.compute)re("server",`${c.slug}-server`,c.name,{...h(ee.compute),label:c.name});for(let[Re,at]of Object.entries(ee?.databases??{}))re("database",Re,Re,at);if(ee?.appDatabase)re("database","application-database","Application database",ee.appDatabase);else if(ee?.database)re("database","application-database","Application database",{engine:ee.database})}let a=new b(r).recoverExpired(),m=r.reconcileOrphanedOperations({policy:"fail"}),E={requeued:a.requeued+m.requeued,failed:a.failed+a.cancelled+m.failed};return{store:r,organization:s,project:c,environments:l,reconciliation:E}}var iE=["project:read","config:read","deployments:read","deployments:create","runtime:read","runtime:logs"];function sd(e,t){let{store:r,organization:n,project:i}=e,o=new Set;for(let s of t){let c=mr(r,s);o.add(c.id);let l=r.getMembershipForActor(n.id,c.id);if(l&&l.source!=="legacy")continue;let a=r.listResources(i.id).filter((q)=>q.kind==="application"&&Object.hasOwn(s.sites,q.slug)),m=s.role==="admin"?"owner":"viewer",E=s.role==="admin"||a.length===0?{type:"organization"}:{type:"resource",id:a[0].id},k=l?l.roleTemplate!==m||gs(l.scope)!==gs(E)?r.updateMembership({id:l.id,roleTemplate:m,scope:E,actorId:c.id}):l:r.createMembership({organizationId:n.id,actorId:c.id,roleTemplate:m,scope:E,source:"legacy"}),O=new Set;if(s.role==="member"&&a.length===0)for(let q of Yr("viewer"))O.add(`deny|${q}|organization|`);for(let q of a){let G=s.sites[q.slug];for(let Y of iE)O.add(`allow|${Y}|resource|${q.id}`);if(G==="owner")O.add(`allow|config:write|resource|${q.id}`)}for(let q of r.listGrants(k.id).filter((G)=>G.source==="legacy")){let G=`${q.effect}|${q.capability}|${q.scope.type}|${q.scope.id??""}`;if(!O.has(G))r.removeGrant(q.id,c.id)}for(let q of O){let[G,Y,re,he]=q.split("|");r.upsertGrant({organizationId:n.id,membershipId:k.id,effect:G,capability:Y,scope:re==="organization"?{type:"organization"}:{type:re,id:he},source:"legacy"})}}for(let s of r.listMemberships(n.id))if(s.source==="legacy"&&!o.has(s.actorId))r.revokeMembership(s.id)}async function ao(e){let{controlPlane:t,environment:r,actor:n}=e,i=mr(t.store,n),o=t.environments.get(r),s=e.resourceSlug&&o?t.store.listResources(t.project.id,o.id).find((m)=>m.slug===e.resourceSlug):void 0,c=new b(t.store,{workerId:`dashboard:${process.pid}`}),l=c.enqueue({projectId:t.project.id,environmentId:o?.id,resourceId:s?.id,actorId:i.id,kind:e.kind,input:e.input??{},lockKey:s?`resource:${s.id}`:o?`environment:${o.id}`:`project:${t.project.id}`,providerKey:s?.provider??"dashboard",buildSlot:e.kind.includes("deploy"),maxAttempts:1,timeoutSeconds:3600,resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;if(!c.claim(l.id)?.operation)throw Error(`Could not claim control-plane operation ${l.id}`);try{let m=await e.execute(),E=typeof m.stdout==="string"?String(m.stdout):"",k=typeof m.stderr==="string"?String(m.stderr):"";if(E)c.appendLog(l.id,E,{stream:"stdout"});if(k)c.appendLog(l.id,k,{stream:"stderr"});let O=m.ok?c.complete(l.id,Dh(m)):c.fail(l.id,oE(m),Dh(m));return{result:m,operation:O}}catch(m){throw c.fail(l.id,m instanceof Error?m.message:String(m),{ok:!1,threw:!0}),m}}function oE(e){let t=e;return String(t.error??t.stderr??"Operation failed")}function Dh(e){let t=e,r=typeof t.stdout==="string"?t.stdout:"",n=typeof t.stderr==="string"?t.stderr:"",i={ok:e.ok,stdoutBytes:Buffer.byteLength(r),stderrBytes:Buffer.byteLength(n)};if(typeof t.operation==="string")i.operation=t.operation;if(typeof t.error==="string")i.error=t.error;return h(i)}var sE=new Set(["singlestore","vitess"]);function dd(e){return sE.has(e)}var cd={mysql:"/var/lib/pantry/mysql/mysqld.sock",mariadb:"/var/lib/pantry/mariadb/mariadbd.sock"};function uo(e){return/^[A-Za-z_][A-Za-z0-9_]{0,62}$/.test(e)}function aE(e){if(e==="postgres"||e==="pgsql")return"postgres";if(e==="mariadb")return"mariadb";if(e==="singlestore")return"singlestore";if(e==="vitess")return"vitess";return"mysql"}function fs(e){let t=e.infrastructure?.compute,r=C(e)?.engine;if(r)return aE(r);let n=t?.managedServices??{};if(n.postgres)return"postgres";if(n.mariadb)return"mariadb";return"mysql"}var $l=(e)=>e.replace(/`/g,"``"),ji=(e)=>e.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),ms=(e)=>`"${e.replace(/"/g,'""')}"`,ad=(e)=>`'${e.replace(/'/g,"''")}'`;function Ml(e,t){return[`mysql --socket=${e==="mariadb"?cd.mariadb:cd.mysql} -u root <<'TS_CLOUD_SQL_EOF'`,...t,"TS_CLOUD_SQL_EOF"]}function Ll(e,t){return[`${fr(t)} -tA <<'TS_CLOUD_PG_EOF'`,...e,"TS_CLOUD_PG_EOF"]}function cE(e,t){if(e==="vitess")return dE(t);if(e==="postgres")return Ll(["SELECT 'DB=' || datname FROM pg_database WHERE datistemplate = false;","SELECT 'USER=' || usename FROM pg_user;"],t);return Ml(e,["SELECT CONCAT('DB=', schema_name) FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');","SELECT DISTINCT CONCAT('USER=', User) FROM mysql.user WHERE User NOT IN ('root', 'mysql.sys', 'mysql.session', 'mysql.infoschema', 'debian-sys-maint');"])}function Ys(e,t,r){let n=t?.host??"127.0.0.1",i=t?.username??"root",o=t?.password??"",s=t?.ssl===!1?"":" --ssl-mode=PREFERRED",c=(a)=>`'${String(a).replace(/'/g,"'\\''")}'`;return[`${o?`MYSQL_PWD=${c(o)} `:""}mysql -h ${c(n)} -P ${t?.port??r} -u ${c(i)}${s} --batch --skip-column-names <<'TS_CLOUD_SQL_EOF'`,...e,"TS_CLOUD_SQL_EOF"]}var Xs=15306;function dE(e){let t=Ys(["SHOW KEYSPACES;"],e,Xs);return t[0]=`${t[0]} | sed 's/^/DB=/'`,t}function uE(e){return Ys(["SHOW KEYSPACES;","SHOW VITESS_SHARDS;","SHOW VITESS_TABLETS;"],e,Xs)}function lE(e){let t=[],r=[],n=[];for(let i of e.split(`
|
|
146
|
+
`)){let o=i.trim();if(!o)continue;let s=o.split("\t").map((c)=>c.trim()).filter(Boolean);if(s.length>=6){let[c,l,a,m,E,k,O]=s;n.push({cell:c??"",keyspace:l??"",shard:a??"",type:m??"",state:E??"",alias:k??"",hostname:O??""});continue}if(s.length===1){let c=s[0];if(c.includes("/")){let[l,a]=c.split("/");if(l&&a)r.push({keyspace:l,shard:a})}else t.push(c)}}return{keyspaces:[...new Set(t)].filter(Boolean).sort(),shards:r,tablets:n}}function pE(e,t,r){if(e==="postgres")return Ll([`SELECT 'CREATE DATABASE ${ms(t)}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = ${ad(t)})\\gexec`],r);return Ml(e,[`CREATE DATABASE IF NOT EXISTS \`${$l(t)}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`])}function gE(e,t,r){let{username:n,password:i,database:o,access:s}=t;if(e==="postgres"){let a=["DO $$ BEGIN",` IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = ${ad(n)}) THEN CREATE ROLE ${ms(n)} LOGIN PASSWORD ${ad(i)};`,` ELSE ALTER ROLE ${ms(n)} LOGIN PASSWORD ${ad(i)}; END IF;`,"END $$;"];if(o)a.push(s==="readonly"?`GRANT CONNECT ON DATABASE ${ms(o)} TO ${ms(n)};`:`GRANT ALL PRIVILEGES ON DATABASE ${ms(o)} TO ${ms(n)};`);return Ll(a,r)}let c=s==="readonly"?"SELECT":"ALL PRIVILEGES",l=[`CREATE USER IF NOT EXISTS '${ji(n)}'@'%' IDENTIFIED BY '${ji(i)}';`,`CREATE USER IF NOT EXISTS '${ji(n)}'@'localhost' IDENTIFIED BY '${ji(i)}';`,`ALTER USER '${ji(n)}'@'%' IDENTIFIED BY '${ji(i)}';`,`ALTER USER '${ji(n)}'@'localhost' IDENTIFIED BY '${ji(i)}';`];if(o)l.push(`GRANT ${c} ON \`${$l(o)}\`.* TO '${ji(n)}'@'%';`,`GRANT ${c} ON \`${$l(o)}\`.* TO '${ji(n)}'@'localhost';`);return l.push("FLUSH PRIVILEGES;"),Ml(e,l)}function mE(e){let t=[],r=[];for(let n of e.split(`
|
|
147
|
+
`)){let i=n.trim();if(i.startsWith("DB="))t.push(i.slice(3));else if(i.startsWith("USER="))r.push(i.slice(5))}return{databases:[...new Set(t)].filter(Boolean).sort(),users:[...new Set(r)].filter(Boolean).sort()}}async function Fn(e,t,r,n){let i;try{i=x({config:e})}catch(l){return{ok:!1,error:`Could not initialize the cloud driver: ${l?.message??l}`}}let o=e.project.slug,s=await i.findComputeTargets({slug:o,environment:t,role:"app"});if(!s.length)return{ok:!1,error:"No app server target was found for this environment."};let c=await i.runRemoteDeploy({targets:[s[0]],commands:["set -uo pipefail",...r],comment:n,tags:{Project:o,Environment:t,Role:"app"}});return{ok:c.success,stdout:c.perInstance?.[0]?.output??"",stderr:c.perInstance?.[0]?.error??c.error??""}}function ud(e,t){return{ok:!1,error:`${t} is not available for ${e}: it is an external cluster, so this box has no engine to administer. ${e==="vitess"?"Create a keyspace with `vtctldclient CreateKeyspace`, and manage vtgate credentials on the cluster.":"Use the provider console or the cluster's own admin connection."}`}}async function Oh(e,t){let r=fs(e);if(dd(r)&&r!=="vitess")return{...ud(r,"Listing databases"),engine:r,databases:[],users:[]};let n=await Fn(e,t,cE(r,C(e)),"ts-cloud db:list"),i=n.ok&&n.stdout?mE(n.stdout):{databases:[],users:[]};return{...n,engine:r,...i}}async function _h(e,t,r){let n=fs(e);if(dd(n))return ud(n,"Creating a database");return Fn(e,t,pE(n,r,C(e)),`ts-cloud db:create ${r}`)}async function Nh(e,t,r){let n=fs(e);if(dd(n))return ud(n,"Creating a database user");return Fn(e,t,gE(n,r,C(e)),`ts-cloud db:user ${r.username}`)}var Bl="/var/backups/ts-cloud/databases";function Do(e,t,r=Bl,n){let o=`${r}/${t}-$TS_CLOUD_BACKUP_STAMP.sql.gz`,s=`mkdir -p ${r}`;if(e==="postgres")return[s,'TS_CLOUD_BACKUP_STAMP="$(date +%Y%m%d-%H%M%S)"',`${fr(n,"pg_dump")} ${t} | gzip > "${o}"`,`echo "BACKUP=${o}"`,`ls -l "${o}"`];let c=e==="mariadb"?cd.mariadb:cd.mysql;return[s,'TS_CLOUD_BACKUP_STAMP="$(date +%Y%m%d-%H%M%S)"',`mysqldump --socket=${c} -u root ${t} | gzip > "${o}"`,`echo "BACKUP=${o}"`,`ls -l "${o}"`]}function fE(e=Bl){return[`ls -1t ${e}/*.sql.gz 2>/dev/null | head -50 | sed 's|^|BACKUP=|' || true`]}function hE(e){let t=[];for(let r of e.split(`
|
|
148
|
+
`)){let n=r.trim();if(!n.startsWith("BACKUP="))continue;let i=n.slice(7),s=(i.split("/").pop()??i).replace(/-\d{8}-\d{6}\.sql\.gz$/,"");if(i)t.push({file:i,database:s})}return t}async function $h(e,t,r){if(!uo(r))return{ok:!1,error:"Database name must be a valid identifier.",database:r};let n=fs(e);if(dd(n))return{...ud(n,"Backing up"),database:r};return{...await Fn(e,t,Do(n,r,Bl,C(e)),`ts-cloud db:backup ${r}`),database:r}}async function Mh(e,t){let r=await Fn(e,t,fE(),"ts-cloud db:backups"),n=r.ok&&r.stdout?hE(r.stdout):[];return{...r,backups:n}}async function Lh(e,t){let r=fs(e),n={keyspaces:[],shards:[],tablets:[]};if(r!=="vitess")return{ok:!1,error:"The configured database engine is not Vitess.",engine:r,...n};let i=await Fn(e,t,uE(C(e)),"ts-cloud vitess:topology"),o=i.ok&&i.stdout?lE(i.stdout):n;return{...i,engine:r,...o}}function Bh(e){return e.filter((t)=>t.state.toUpperCase()!=="SERVING")}function jh(e){let t=new Set(e.tablets.filter((r)=>r.type.toUpperCase()==="PRIMARY"&&r.state.toUpperCase()==="SERVING").map((r)=>`${r.keyspace}/${r.shard}`));return e.shards.filter((r)=>!t.has(`${r.keyspace}/${r.shard}`))}var jl="/usr/local/bin/vtctldclient",yE="21.0.0";function pd(e){return`'${String(e).split("'").join("'\\''")}'`}function gd(e){return C(e)?.vitess??{}}function Fh(e){return/^[A-Za-z_][A-Za-z0-9_]{0,63}$/.test(e)}function bE(e){return/^[0-9a-f]{8}(?:_[0-9a-f]{4}){3}_[0-9a-f]{12}$/i.test(e)}function SE(e=yE){let t=pd(e);return[`if ${jl} --version 2>/dev/null | grep -q ${t}; then echo "vtctldclient ${e} already installed"; else`," command -v curl >/dev/null 2>&1 || (apt-get update -y && apt-get install -y curl ca-certificates)",' if [ "$(uname -m)" != "x86_64" ]; then',' echo "vtctldclient: Vitess publishes only an x86_64 release tarball; this box is $(uname -m). Build from source or install via pantry." >&2'," exit 1"," fi",' tmp="$(mktemp -d)"',` api="https://api.github.com/repos/vitessio/vitess/releases/tags/v${e}"`,` url="$(curl -fsSL "$api" | grep -oE '"browser_download_url"[[:space:]]*:[[:space:]]*"[^"]+vitess-[0-9][^"]*\\.tar\\.gz"' | head -1 | sed -E 's/.*"(https[^"]+)"/\\1/')"`,' if [ -z "$url" ]; then echo "vtctldclient: no release tarball found for v'+e+'" >&2; rm -rf "$tmp"; exit 1; fi',` curl -fsSL "$url" | tar -xz -C "$tmp" --strip-components=2 --wildcards --occurrence=1 '*/bin/vtctldclient' || true`,' if [ ! -s "$tmp/vtctldclient" ]; then',' echo "vtctldclient: could not extract the binary from $url" >&2',' rm -rf "$tmp"; exit 1'," fi",` install -m 0755 "$tmp/vtctldclient" ${jl}`,' rm -rf "$tmp"',` echo "installed vtctldclient ${e}"`,"fi"]}function Uh(e){if(!e.vtctldAddr)return null;return`${jl} --server ${pd(e.vtctldAddr)}`}function vE(e,t,r={}){let n=Uh(e);if(!n)return null;let i=r.sharded?" --sharded":"";return[`${n} CreateKeyspace${i} ${pd(t)}`]}function wE(e,t,r){let n=Uh(e);if(!n)return null;return['vschema_tmp="$(mktemp)"',`cat > "$vschema_tmp" <<'TS_CLOUD_VSCHEMA_EOF'`,r,"TS_CLOUD_VSCHEMA_EOF",`${n} ApplyVSchema --vschema-file "$vschema_tmp" ${pd(t)}`,'rm -f "$vschema_tmp"']}function IE(e,t,r="vitess"){return Ys([`SET @@ddl_strategy='${r}';`,t.endsWith(";")?t:`${t};`],e,Xs)}function CE(e,t){let r=t?[`USE ${t.replace(/[^A-Z0-9_]/gi,"")};`,"SHOW VITESS_MIGRATIONS;"]:["SHOW VITESS_MIGRATIONS;"],n=Ys(r,e,Xs);return n[0]=n[0].replace(" --skip-column-names",""),n}function EE(e){let t=e.split(`
|
|
149
|
+
`).map((s)=>s.trimEnd()).filter((s)=>s.trim().length>0);if(t.length===0)return[];let r=t[0].split("\t").map((s)=>s.trim()),n=(s)=>r.indexOf(s),i={uuid:n("migration_uuid"),keyspace:n("keyspace"),shard:n("shard"),table:n("mysql_table"),status:n("migration_status"),strategy:n("strategy"),added:n("added_timestamp"),completed:n("completed_timestamp"),progress:n("progress")};if(i.uuid===-1)return[];let o=[];for(let s of t.slice(1)){let c=s.split("\t"),l=(m)=>m>=0?(c[m]??"").trim():"",a=l(i.uuid);if(!a)continue;o.push({uuid:a,keyspace:l(i.keyspace),shard:l(i.shard),table:l(i.table),status:l(i.status),strategy:l(i.strategy),added:l(i.added),completed:l(i.completed),progress:l(i.progress)})}return o}function TE(e){return e.filter((t)=>t.status.toLowerCase()==="failed")}function AE(e){return e.filter((t)=>["running","queued","ready"].includes(t.status.toLowerCase()))}function kE(e,t,r){let n=r.toUpperCase();return Ys([`ALTER VITESS_MIGRATION '${t}' ${n};`],e,Xs)}function Zs(e){if(fs(e)!=="vitess")return{ok:!1,error:"The configured database engine is not Vitess."};return null}function ld(e){if(!e.vtctldAddr)return{ok:!1,error:"No vtctld address is configured. Creating keyspaces and applying a VSchema are topology operations that vtgate cannot perform. Set `infrastructure.appDatabase.vitess.vtctldAddr` (for example `vtctld.internal:15999`) and redeploy."};return null}async function zh(e,t){let r=Zs(e);if(r)return r;let n=gd(e);return Fn(e,t,SE(n.clientVersion),"ts-cloud vitess:install-client")}async function Vh(e,t,r,n={}){let i=Zs(e);if(i)return{...i,keyspace:r};if(!Fh(r))return{ok:!1,error:"Keyspace name must be a valid identifier.",keyspace:r};let o=gd(e),s=ld(o);if(s)return{...s,keyspace:r};let c=vE(o,r,n);if(!c)return{...ld({}),keyspace:r};return{...await Fn(e,t,c,`ts-cloud vitess:create-keyspace ${r}`),keyspace:r}}async function qh(e,t,r,n){let i=Zs(e);if(i)return{...i,keyspace:r};if(!Fh(r))return{ok:!1,error:"Keyspace name must be a valid identifier.",keyspace:r};try{let a=JSON.parse(n);if(!a||typeof a!=="object")return{ok:!1,error:"The VSchema must be a JSON object.",keyspace:r}}catch(a){return{ok:!1,error:`The VSchema is not valid JSON: ${a?.message??a}`,keyspace:r}}let o=gd(e),s=ld(o);if(s)return{...s,keyspace:r};let c=wE(o,r,n);if(!c)return{...ld({}),keyspace:r};return{...await Fn(e,t,c,`ts-cloud vitess:apply-vschema ${r}`),keyspace:r}}async function Jh(e,t,r){let n=Zs(e);if(n)return n;if(!r.trim())return{ok:!1,error:"No SQL was provided."};let i=gd(e);return Fn(e,t,IE(C(e),r,i.ddlStrategy??"vitess"),"ts-cloud vitess:apply-schema")}async function Wh(e,t,r){let n=Zs(e);if(n)return{...n,migrations:[],failed:[],running:[]};let i=await Fn(e,t,CE(C(e),r),"ts-cloud vitess:migrations"),o=i.ok&&i.stdout?EE(i.stdout):[];return{...i,migrations:o,failed:TE(o),running:AE(o)}}async function Hh(e,t,r,n){let i=Zs(e);if(i)return{...i,uuid:r};if(!bE(r))return{ok:!1,error:"Migration UUID is not in the expected format.",uuid:r};return{...await Fn(e,t,kE(C(e),r,n),`ts-cloud vitess:migration ${n} ${r}`),uuid:r}}function RE(e){let t=e.infrastructure?.appDatabase;if(t?.engine&&t.engine!=="vitess")return`This project already declares ${t.engine} as its application database.`;let r=e.infrastructure?.compute?.managedServices,n=r?["mysql","mariadb","postgres"].find((i)=>Boolean(r[i])):void 0;if(n)return`This server already declares the ${n} database service.`;return}function PE(e,t){let r=t.keyspace.trim(),n=t.username.trim(),i=t.password,o=RE(e);if(o)throw Error(o);if(!uo(r))throw Error("Keyspace must contain letters, numbers, or underscores and cannot start with a number.");if(!uo(n))throw Error("Username must contain letters, numbers, or underscores and cannot start with a number.");if(i.length<16)throw Error("Password must contain at least 16 characters.");if(t.confirm!==r)throw Error(`Type "${r}" to confirm Vitess provisioning.`);let s={mode:"cluster",cell:"zone1",keyspaces:[{name:r,sharded:t.sharded===!0}],vtgatePort:15306,username:n,password:i,bindAddress:"127.0.0.1"};return{service:s,appDatabase:{engine:"vitess",name:r,username:n,host:"127.0.0.1",port:15306,ssl:!1},commands:[...gr(),...co(s)]}}async function Gh(e,t,r){let n=PE(e,r);return{...await Fn(e,t,n.commands,`ts-cloud vitess:provision ${n.appDatabase.name}`),database:n.appDatabase,service:Object.fromEntries(Object.entries(n.service).filter(([o])=>o!=="password"))}}var xE={capability:"runtime:terminal",scope:"organization"};var DE={"GET /api/health":{capability:"project:read",anyUser:!0},"GET /api/dashboard-data":{capability:"project:read",anyUser:!0},"GET /api/config":{capability:"config:read",anyUser:!0},"GET /api/me":{capability:"project:read",anyUser:!0},"GET /api/search":{capability:"project:read",anyUser:!0},"GET /api/search/preferences":{capability:"project:read",anyUser:!0},"POST /api/search/preferences":{capability:"project:read",anyUser:!0},"DELETE /api/search/preferences":{capability:"project:read",anyUser:!0},"GET /api/auth/security":{capability:"project:read",anyUser:!0},"GET /api/auth/sessions":{capability:"project:read",anyUser:!0},"DELETE /api/auth/sessions":{capability:"project:read",anyUser:!0},"POST /api/auth/sessions/revoke-others":{capability:"project:read",anyUser:!0},"POST /api/auth/password/change":{capability:"project:read",anyUser:!0},"POST /api/auth/mfa/enroll":{capability:"project:read",anyUser:!0},"POST /api/auth/mfa/verify":{capability:"project:read",anyUser:!0},"DELETE /api/auth/mfa":{capability:"project:read",anyUser:!0},"POST /api/auth/step-up":{capability:"project:read",anyUser:!0},"GET /api/auth/oidc/providers":{capability:"users:read",scope:"organization"},"POST /api/auth/oidc/providers":{capability:"users:manage",scope:"organization"},"PATCH /api/auth/oidc/providers":{capability:"users:manage",scope:"organization"},"GET /api/automation":{capability:"users:read",scope:"organization"},"POST /api/automation/service-accounts":{capability:"users:manage",scope:"organization"},"PATCH /api/automation/service-accounts":{capability:"users:manage",scope:"organization"},"POST /api/automation/tokens":{capability:"users:manage",scope:"organization"},"POST /api/automation/tokens/rotate":{capability:"users:manage",scope:"organization"},"DELETE /api/automation/tokens":{capability:"users:manage",scope:"organization"},"GET /api/security/posture":{capability:"security:read"},"GET /api/security/export":{capability:"security:read"},"POST /api/security/scan":{capability:"security:manage"},"POST /api/security/review":{capability:"deployments:create"},"POST /api/security/policies":{capability:"security:manage"},"PATCH /api/security/policies":{capability:"security:manage"},"POST /api/security/waivers":{capability:"security:waive"},"DELETE /api/security/waivers":{capability:"security:waive"},"PATCH /api/security/findings":{capability:"security:manage"},"POST /api/security/comments":{capability:"security:manage"},"GET /api/sources":{capability:"sources:read"},"POST /api/sources/connections":{capability:"sources:manage"},"PATCH /api/sources/connections":{capability:"sources:manage"},"DELETE /api/sources/connections":{capability:"sources:manage"},"POST /api/sources/deploy-keys":{capability:"sources:manage"},"DELETE /api/sources/deploy-keys":{capability:"sources:manage"},"POST /api/sources/repositories/sync":{capability:"sources:manage"},"GET /api/sources/references":{capability:"sources:read"},"POST /api/sources/bindings":{capability:"sources:manage"},"PATCH /api/sources/bindings":{capability:"sources:manage"},"POST /api/sources/webhooks":{capability:"sources:manage"},"PATCH /api/sources/webhooks":{capability:"sources:manage"},"DELETE /api/sources/webhooks":{capability:"sources:manage"},"GET /api/onboarding":{capability:"applications:read"},"POST /api/onboarding/detect":{capability:"applications:manage"},"POST /api/onboarding/plan":{capability:"applications:manage"},"POST /api/onboarding/drafts":{capability:"applications:manage"},"PATCH /api/onboarding/drafts":{capability:"applications:manage"},"POST /api/onboarding/artifacts":{capability:"applications:manage"},"POST /api/onboarding/registries":{capability:"applications:manage"},"PATCH /api/onboarding/registries":{capability:"applications:manage"},"DELETE /api/onboarding/registries":{capability:"applications:manage"},"POST /api/onboarding/apply":{capability:"applications:manage"},"GET /api/compose":{capability:"applications:read",anyUser:!0},"POST /api/compose/preview":{capability:"applications:manage",anyUser:!0},"POST /api/compose/import":{capability:"applications:manage",anyUser:!0},"POST /api/compose/template":{capability:"applications:manage",anyUser:!0},"POST /api/compose/action":{capability:"project:read",anyUser:!0},"POST /api/compose/logs":{capability:"runtime:logs",anyUser:!0},"POST /api/compose/shell":{capability:"runtime:terminal",scope:"organization"},"GET /api/compose/import":{capability:"applications:manage"},"GET /api/compose/template":{capability:"applications:manage"},"GET /api/compose/logs":{capability:"runtime:logs"},"GET /api/compose/shell":{capability:"runtime:terminal",scope:"organization"},"GET /api/organization":{capability:"users:read",scope:"organization"},"GET /api/organization/invitations":{capability:"users:read",scope:"organization"},"POST /api/organization/invitations":{capability:"users:manage",scope:"organization"},"DELETE /api/organization/invitations":{capability:"users:manage",scope:"organization"},"POST /api/organization/invitations/resend":{capability:"users:manage",scope:"organization"},"PATCH /api/organization/memberships":{capability:"users:manage",scope:"organization"},"DELETE /api/organization/memberships":{capability:"users:manage",scope:"organization"},"POST /api/organization/grants":{capability:"users:manage",scope:"organization"},"DELETE /api/organization/grants":{capability:"users:manage",scope:"organization"},"GET /api/control-plane/operations":{capability:"deployments:read"},"GET /api/control-plane/events":{capability:"audit:read"},"GET /api/queue":{capability:"deployments:read",anyUser:!0},"GET /api/queue/logs":{capability:"deployments:read",anyUser:!0},"GET /api/queue/stream":{capability:"deployments:read",anyUser:!0},"POST /api/queue/cancel":{capability:"deployments:cancel",anyUser:!0},"POST /api/queue/retry":{capability:"deployments:create",anyUser:!0},"GET /api/queue/settings":{capability:"deployments:read"},"PATCH /api/queue/settings":{capability:"automation:manage",scope:"organization"},"DELETE /api/queue/history":{capability:"automation:manage",scope:"organization"},"GET /api/previews":{capability:"deployments:read",anyUser:!0},"GET /api/releases":{capability:"deployments:read",anyUser:!0},"POST /api/releases/action":{capability:"deployments:create",anyUser:!0},"POST /api/previews/deploy":{capability:"deployments:create",anyUser:!0},"POST /api/previews/destroy":{capability:"deployments:cancel",anyUser:!0},"POST /api/previews/extend":{capability:"deployments:create",anyUser:!0},"POST /api/previews/rebuild":{capability:"deployments:create",anyUser:!0},"POST /api/previews/definitions":{capability:"config:write",anyUser:!0},"POST /api/previews/cleanup":{capability:"automation:manage",scope:"organization"},"GET /api/tags":{capability:"project:read"},"POST /api/tags":{capability:"tags:manage"},"DELETE /api/tags":{capability:"tags:manage"},"POST /api/sites/deploy":{capability:"deployments:create",scope:"site",siteFrom:"body"},"PATCH /api/sites":{capability:"config:write",scope:"site",siteFrom:"body"},"POST /api/sites":{capability:"config:write"},"DELETE /api/sites":{capability:"config:write"},"POST /api/env":{capability:"config:write"},"GET /api/ssh-keys":{capability:"fleet:read"},"POST /api/ssh-keys":{capability:"fleet:manage"},"DELETE /api/ssh-keys":{capability:"fleet:manage"},"GET /api/firewall":{capability:"fleet:read"},"POST /api/firewall":{capability:"fleet:manage"},"DELETE /api/firewall":{capability:"fleet:manage"},"GET /api/databases":{capability:"data:read"},"POST /api/databases":{capability:"data:admin"},"GET /api/databases/vitess":{capability:"data:read"},"GET /api/databases/vitess/migrations":{capability:"data:read"},"POST /api/databases/vitess/migrations/action":{capability:"data:admin"},"POST /api/databases/vitess/provision":{capability:"runtime:terminal",scope:"organization"},"POST /api/databases/vitess/keyspaces":{capability:"data:admin"},"POST /api/databases/vitess/vschema":{capability:"data:admin"},"POST /api/databases/vitess/schema":{capability:"data:admin"},"POST /api/databases/vitess/install-client":{capability:"data:admin"},"GET /api/databases/backups":{capability:"backups:read"},"POST /api/databases/backup":{capability:"backups:create"},"POST /api/databases/users":{capability:"data:admin"},"GET /api/data-services":{capability:"data:read"},"GET /api/data-services/capabilities":{capability:"data:read"},"GET /api/data-services/connections":{capability:"data:read"},"POST /api/data-services/preview":{capability:"data:read"},"POST /api/data-services":{capability:"data:admin"},"POST /api/data-services/action":{capability:"data:admin"},"POST /api/data-services/dependencies":{capability:"data:admin"},"POST /api/data-services/management":{capability:"data:admin"},"POST /api/data-services/reveal":{capability:"data:admin"},"GET /api/backups":{capability:"backups:read"},"POST /api/backups/destinations":{capability:"backups:create"},"POST /api/backups/destinations/test":{capability:"backups:create"},"POST /api/backups/policies":{capability:"backups:create"},"POST /api/backups/run":{capability:"backups:create"},"POST /api/backups/verify":{capability:"backups:create"},"POST /api/backups/restore":{capability:"backups:restore"},"POST /api/backups/recovery-points":{capability:"backups:create"},"POST /api/backups/retention":{capability:"backups:create"},"GET /api/configuration":{capability:"config:read"},"GET /api/configuration/export":{capability:"config:read"},"POST /api/configuration/plan":{capability:"config:read"},"POST /api/configuration":{capability:"config:write"},"POST /api/configuration/import":{capability:"config:write"},"POST /api/configuration/dependencies":{capability:"config:write"},"POST /api/configuration/transfer":{capability:"config:write"},"POST /api/configuration/bulk":{capability:"config:write"},"POST /api/configuration/reveal":{capability:"secrets:read"},"DELETE /api/configuration":{capability:"config:write"},"GET /api/volumes":{capability:"data:read"},"POST /api/volumes":{capability:"data:admin"},"POST /api/volumes/attach":{capability:"data:admin"},"POST /api/volumes/detach":{capability:"data:admin"},"POST /api/volumes/resize":{capability:"data:admin"},"POST /api/volumes/snapshot":{capability:"backups:create"},"POST /api/volumes/restore":{capability:"backups:restore"},"POST /api/volumes/adopt":{capability:"data:admin"},"POST /api/volumes/discover":{capability:"data:read"},"DELETE /api/volumes":{capability:"data:admin"},"GET /api/fleet":{capability:"fleet:read"},"POST /api/fleet":{capability:"fleet:manage"},"POST /api/fleet/action":{capability:"fleet:manage"},"GET /api/capacity":{capability:"fleet:read"},"POST /api/capacity":{capability:"fleet:manage"},"POST /api/capacity/member":{capability:"fleet:manage"},"POST /api/capacity/explain":{capability:"fleet:read"},"POST /api/capacity/action":{capability:"fleet:manage"},"GET /api/regions":{capability:"config:read"},"POST /api/regions":{capability:"config:write"},"POST /api/regions/action":{capability:"config:write"},"GET /api/maintenance":{capability:"automation:read"},"POST /api/maintenance/cleanup-preview":{capability:"automation:manage"},"POST /api/maintenance/cleanup-apply":{capability:"automation:manage"},"POST /api/maintenance/drill":{capability:"automation:manage"},"POST /api/maintenance/drill-run":{capability:"automation:manage"},"GET /api/actions":{capability:"runtime:read"},"GET /api/runtime/workloads":{capability:"runtime:read"},"GET /api/runtime/logs":{capability:"runtime:logs"},"POST /api/runtime/log-sessions":{capability:"runtime:logs"},"GET /api/runtime/log-sessions":{capability:"runtime:logs"},"GET /api/runtime/log-stream":{capability:"runtime:logs"},"DELETE /api/runtime/log-sessions":{capability:"runtime:logs"},"POST /api/runtime/exec-sessions":{capability:"runtime:terminal",scope:"organization"},"GET /api/runtime/exec-sessions":{capability:"runtime:terminal",scope:"organization"},"GET /api/runtime/exec-stream":{capability:"runtime:terminal",scope:"organization"},"DELETE /api/runtime/exec-sessions":{capability:"runtime:terminal",scope:"organization"},"POST /api/runtime/files/read":{capability:"runtime:terminal",scope:"organization"},"POST /api/runtime/files/write":{capability:"runtime:terminal",scope:"organization"},"POST /api/runtime/operations":{capability:"runtime:restart"},"GET /api/telemetry/status":{capability:"runtime:read"},"GET /api/telemetry/settings":{capability:"runtime:read"},"PATCH /api/telemetry/settings":{capability:"config:write",scope:"organization"},"GET /api/telemetry/query":{capability:"runtime:logs"},"GET /api/telemetry/tail":{capability:"runtime:logs"},"GET /api/telemetry/series":{capability:"runtime:read"},"POST /api/telemetry/refresh":{capability:"runtime:logs"},"POST /api/telemetry/export":{capability:"runtime:logs"},"GET /api/telemetry/saved-queries":{capability:"runtime:logs"},"POST /api/telemetry/saved-queries":{capability:"runtime:logs"},"DELETE /api/telemetry/saved-queries":{capability:"runtime:logs"},"GET /api/health/checks":{capability:"runtime:read"},"POST /api/health/checks":{capability:"config:write"},"PATCH /api/health/checks":{capability:"config:write"},"POST /api/health/checks/test":{capability:"runtime:read"},"POST /api/health/checks/run":{capability:"runtime:restart"},"GET /api/protection":{capability:"security:read"},"POST /api/protection/attack-mode":{capability:"security:manage"},"POST /api/protection/pause":{capability:"security:manage"},"GET /api/protection/ip-rules":{capability:"security:read"},"POST /api/protection/ip-rules":{capability:"security:manage"},"DELETE /api/protection/ip-rules":{capability:"security:manage"},"GET /api/usage":{capability:"billing:read"},"GET /api/spend/budgets":{capability:"billing:read"},"POST /api/spend/budgets":{capability:"billing:manage"},"PATCH /api/spend/budgets":{capability:"billing:manage"},"DELETE /api/spend/budgets":{capability:"billing:manage"},"POST /api/spend/check":{capability:"billing:manage"},"GET /api/spend/enforcement":{capability:"billing:read"},"POST /api/spend/release":{capability:"billing:manage"},"GET /api/spend/anomalies":{capability:"billing:read"},"POST /api/spend/anomalies/acknowledge":{capability:"billing:manage"},"GET /api/alerts":{capability:"runtime:read"},"GET /api/alerts/rules":{capability:"runtime:read"},"POST /api/alerts/rules":{capability:"config:write"},"PATCH /api/alerts/rules":{capability:"config:write"},"POST /api/alerts/evaluate":{capability:"runtime:restart"},"POST /api/alerts/action":{capability:"runtime:restart"},"POST /api/alerts/silences":{capability:"config:write"},"GET /api/notifications/channels":{capability:"automation:read",scope:"organization"},"POST /api/notifications/channels":{capability:"automation:manage",scope:"organization"},"PATCH /api/notifications/channels":{capability:"automation:manage",scope:"organization"},"POST /api/notifications/channels/test":{capability:"automation:manage",scope:"organization"},"GET /api/notifications/routes":{capability:"automation:read",scope:"organization"},"POST /api/notifications/routes":{capability:"automation:manage",scope:"organization"},"PATCH /api/notifications/routes":{capability:"automation:manage",scope:"organization"},"POST /api/notifications/routes/preview":{capability:"automation:read",scope:"organization"},"GET /api/notifications/deliveries":{capability:"automation:read",scope:"organization"},"POST /api/notifications/deliveries/retry":{capability:"automation:manage",scope:"organization"},"GET /api/jobs":{capability:"automation:read"},"POST /api/jobs":{capability:"automation:manage"},"PATCH /api/jobs":{capability:"automation:manage"},"POST /api/jobs/preview":{capability:"automation:read"},"POST /api/jobs/action":{capability:"automation:manage"},"POST /api/jobs/reconcile":{capability:"automation:manage"},"GET /api/jobs/history":{capability:"automation:read"},"GET /api/workers":{capability:"automation:read"},"POST /api/workers/action":{capability:"automation:manage"},"POST /api/actions/run":{capability:"fleet:manage"},"GET /api/server/operations":{capability:"fleet:read"},"POST /api/server/operations/run":{capability:"fleet:manage"},"POST /api/server/command":{capability:"runtime:terminal",scope:"organization"},"GET /api/terminal":{capability:"runtime:terminal",scope:"organization"},"GET /api/users":{capability:"users:read",scope:"organization"},"POST /api/users":{capability:"users:manage",scope:"organization"},"DELETE /api/users":{capability:"users:manage",scope:"organization"},"GET /api/serverless/operations":{capability:"deployments:read"},"POST /api/serverless/operations/run":{capability:"deployments:create"},"POST /api/serverless/command":{capability:"runtime:terminal",scope:"organization"},"GET /api/serverless/dlq":{capability:"data:read"},"POST /api/serverless/dlq/redrive":{capability:"data:write"},"POST /api/serverless/dlq/purge":{capability:"data:admin"},"GET /api/serverless/secrets":{capability:"secrets:read"},"POST /api/serverless/secrets":{capability:"secrets:write"},"DELETE /api/serverless/secrets":{capability:"secrets:write"},"POST /api/serverless/functions/config":{capability:"config:write"},"GET /api/serverless/alarms":{capability:"runtime:read"},"POST /api/serverless/alarms":{capability:"config:write"},"DELETE /api/serverless/alarms":{capability:"config:write"},"GET /api/serverless/traces":{capability:"runtime:read"},"POST /api/serverless/scheduler":{capability:"automation:manage"}};function Fl(e,t){return DE[`${e.toUpperCase()} ${t}`]??xE}import{createHmac as OE,randomBytes as _E,timingSafeEqual as NE}from"node:crypto";import{chmodSync as $E,existsSync as ME,mkdirSync as LE,readFileSync as BE,writeFileSync as jE}from"node:fs";import{dirname as FE}from"node:path";var Ma="ts_cloud_session";var UE=28800000;function Kh(e){let t=process.env.TS_CLOUD_DASHBOARD_SECRET?.trim();if(t)return t;let r=A(e,"dashboard-secret");try{if(ME(r)){let i=BE(r,"utf8").trim();if(i)return i}}catch{}let n=_E(32).toString("base64url");try{LE(FE(r),{recursive:!0}),jE(r,`${n}
|
|
150
|
+
`),$E(r,384)}catch{}return n}function zE(e,t){return OE("sha256",t).update(e).digest("base64url")}function Qh(e,t){if(!e)return null;let r=e.lastIndexOf(".");if(r<=0)return null;let n=e.slice(0,r),i=e.slice(r+1),o=zE(n,t),s=Buffer.from(i),c=Buffer.from(o);if(s.length!==c.length||!NE(s,c))return null;try{let l=JSON.parse(Buffer.from(n,"base64url").toString("utf8"));if(typeof l?.u!=="string"||typeof l?.exp!=="number")return null;if(l.mv!==void 0&&(!l.mv||typeof l.mv!=="object"||Array.isArray(l.mv)||Object.values(l.mv).some((a)=>!Number.isInteger(a)||a<1)))return null;if(Date.now()>=l.exp)return null;return l}catch{return null}}function Ul(e,t){if(!e)return;for(let r of e.split(";")){let n=r.indexOf("=");if(n<0)continue;if(r.slice(0,n).trim()===t)return decodeURIComponent(r.slice(n+1).trim())}return}function ea(e,t={secure:!0}){let r=Math.floor((t.maxAgeMs??UE)/1000),n=[`${Ma}=${encodeURIComponent(e)}`,"Path=/","HttpOnly","SameSite=Lax",`Max-Age=${r}`];if(t.secure)n.push("Secure");return n.join("; ")}function md(e={secure:!0}){let t=[`${Ma}=`,"Path=/","HttpOnly","SameSite=Lax","Max-Age=0"];if(e.secure)t.push("Secure");return t.join("; ")}import{chmodSync as VE,existsSync as qE,mkdirSync as JE,readFileSync as WE,writeFileSync as HE}from"node:fs";import{dirname as GE}from"node:path";function Yh(){return Ke("dashboard-users.json")}function fd(e){return/^[a-z0-9][a-z0-9._-]{1,31}$/i.test(e)}function KE(e){if(!e||typeof e.username!=="string"||!fd(e.username)||typeof e.passwordHash!=="string")return null;let t=e.role==="admin"?"admin":"member",r={};if(e.sites&&typeof e.sites==="object"){for(let[n,i]of Object.entries(e.sites))if(i==="owner"||i==="collaborator")r[n]=i}return{username:e.username,passwordHash:e.passwordHash,role:t,sites:r,name:typeof e.name==="string"?e.name:void 0,email:typeof e.email==="string"?e.email.trim().toLowerCase():void 0,createdAt:typeof e.createdAt==="string"?e.createdAt:void 0}}function QE(e){try{let t=JSON.parse(e);if(!Array.isArray(t?.users))return[];return t.users.map(KE).filter((r)=>r!==null)}catch{return[]}}function Xh(e){return A(e,"dashboard-users.json")}function Jn(e){let t=Xh(e);if(!qE(t))return[];try{return QE(WE(t,"utf8"))}catch{return[]}}function hd(e,t){let r=Xh(e);JE(GE(r),{recursive:!0}),HE(r,`${JSON.stringify({users:t},null,2)}
|
|
151
|
+
`),VE(r,384)}function pi(e,t){let r=t.trim().toLowerCase();return e.find((n)=>n.username.toLowerCase()===r)}function Zh(e,t="admin"){let r=Jn(e);if(r.some((s)=>s.role==="admin"))return{users:r};let n=process.env.TS_CLOUD_UI_PASSWORD?.trim()||Nl(),i={username:t,passwordHash:No(n),role:"admin",sites:{},name:"Administrator",createdAt:new Date().toISOString()},o=[...r,i];return hd(e,o),{users:o,generated:{username:t,password:n}}}function La(e,t){let r=Jn(e),n=pi(r,t.username),i=t.password?.trim()||(n?void 0:Nl()),o={username:n?.username??t.username,passwordHash:i?No(i):n.passwordHash,role:n?.role??"member",sites:t.sites,name:t.name??n?.name,email:t.email?.trim().toLowerCase()??n?.email,createdAt:n?.createdAt??new Date().toISOString()},s=n?r.map((c)=>c.username.toLowerCase()===o.username.toLowerCase()?o:c):[...r,o];return hd(e,s),{user:o,password:i}}function yd(e,t,r){let n=Jn(e),i=pi(n,t);if(!i)throw Error("Authentication user was not found");let o={...i,passwordHash:r};return hd(e,n.map((s)=>s.username.toLowerCase()===i.username.toLowerCase()?o:s)),o}function zl(e,t){let r=Jn(e),n=pi(r,t);if(!n)return{ok:!1,error:`No such user: ${t}`};if(n.role==="admin"&&r.filter((i)=>i.role==="admin").length===1)return{ok:!1,error:"Cannot remove the last admin."};return hd(e,r.filter((i)=>i.username.toLowerCase()!==n.username.toLowerCase())),{ok:!0}}function ta(e){return{username:e.username,name:e.name??e.username,role:e.role,email:e.email,sites:e.sites,siteCount:Object.keys(e.sites).length,createdAt:e.createdAt}}var YE={username:"local",passwordHash:"",role:"admin",sites:{},name:"Local (auth disabled)"};function ey(e){let{cwd:t,enabled:r,secret:n,authorization:i,authentication:o}=e,s=(l)=>{if(!o)return;let a=Ul(l.headers.get("cookie"),Ma);return a?.startsWith("v2.")?o.verifySessionToken(a):void 0},c=(l)=>{let a=i.store.getActorByExternalId("user",`dashboard:${l.username.toLowerCase()}`),m=a?i.store.getMembershipForActor(i.organizationId,a.id):void 0;return{actor:a,membership:m}};return{enabled:r,resolveUser(l){if(!r)return YE;let a=Ul(l.headers.get("cookie"),Ma),m=s(l),E=m?void 0:Qh(a,n),k=m?.identity.username??E?.u;if(!k)return null;let O=pi(Jn(t),k);if(!O)return null;let{membership:q}=c(O);if(!q||q.status!=="active"||!m&&E?.mv?.[i.organizationId]!==q.sessionVersion)return null;if(!q.lastActiveAt||Date.now()-new Date(q.lastActiveAt).getTime()>300000)i.store.touchMembership(q.id);return O},resolveSession(l){return s(l)?.session??null},check(l,a,m,E){if(!r)return{ok:!0};if(!m)return{ok:!1,status:401,error:"Sign in to continue.",unauthenticated:!0};let k=Fl(l.method,a);if(k.anyUser)return{ok:!0};if(k.siteFrom==="body"&&!E)return{ok:!1,status:400,error:"This request must name a site."};let{membership:O}=c(m);if(!O)return{ok:!1,status:401,error:"Sign in to continue.",unauthenticated:!0};let q=k.scope==="organization"?{organizationId:i.organizationId}:i.store.resolveAuthorizationTarget(i.organizationId,{type:"project",id:i.projectId});if(k.scope==="site"){let Y=new URL(l.url).searchParams.get("env")??i.defaultEnvironment,re=i.store.getEnvironmentBySlug(i.projectId,Y),he=i.store.listResources(i.projectId,re?.id).find((ee)=>ee.kind==="application"&&ee.slug===E);q=he?i.store.resolveAuthorizationTarget(i.organizationId,{type:"resource",id:he.id}):void 0}if(!(q?Z({membership:O,grants:i.store.listGrants(O.id),capability:k.capability,target:q}):{allowed:!1}).allowed)return{ok:!1,status:403,error:"You do not have access to this."};return{ok:!0}}}}async function ty(e,t){if(Fl(e.method,t).siteFrom!=="body")return;try{let n=await e.clone().json();return String(n?.name??"").trim()||void 0}catch{return}}import{createHash as XE}from"node:crypto";function ry(e,t,r){for(let n of r){let i=mr(t.store,n);if(e.getIdentityByActor(i.id))continue;e.createIdentity({actorId:i.id,username:n.username,email:n.email,emailVerified:!!n.email,passwordHash:n.passwordHash,requiresPasswordUpgrade:!0})}}function ZE(e,t,r){let n=r.split("@")[0].toLowerCase().replace(/[^a-z0-9._-]/g,"-").replace(/^[^a-z0-9]+/,"").slice(0,24),i=/^[a-z0-9][a-z0-9._-]{1,31}$/.test(n)?n:"sso-user";if(!e.getIdentityByUsername(i)&&!pi(t,i))return i;let o=XE("sha256").update(r).digest("hex").slice(0,7);return`${i.slice(0,24)}-${o}`}function ny(e,t,r,n){if(n.provider.organizationId!==t.organization.id)throw Error("OIDC provider is not configured for this organization");let i=e.getOidcSubject(n.provider.id,n.subject),o=i?e.getIdentity(i.identityId):e.getIdentityByEmail(n.email);if(o?.disabledAt)throw Error("OIDC identity is disabled");if(!i&&o&&!o.emailVerifiedAt)throw Error("OIDC cannot automatically link an unverified local email address");let s=Jn(r),c=!1,l=o?pi(s,o.username):void 0;if(o&&!l)throw Error("OIDC identity has no dashboard user");if(!o){let E=ZE(e,s,n.email);l=La(r,{username:E,name:n.name,email:n.email,sites:{}}).user;let O=mr(t.store,l);o=e.createIdentity({actorId:O.id,username:l.username,email:n.email,emailVerified:!0,passwordHash:l.passwordHash}),c=!0}else if(o.email!==n.email)o=e.setVerifiedEmail(o.id,n.email);let a=t.store.getActor(o.actorId);if(!a)throw Error("OIDC identity actor was not found");let m=t.store.getMembershipForActor(t.organization.id,a.id);if(m?.status==="revoked")throw Error("OIDC organization membership is revoked");if(!m)t.store.createMembership({organizationId:t.organization.id,actorId:a.id,roleTemplate:n.provider.defaultRole,scope:{type:"organization"},source:"manual"});return e.linkOidcSubject(n.provider.id,o.id,n.subject,n.email),{identity:o,user:l,provisioned:c}}function iy(e,t,r){let n=t.store.getMembershipForActor(t.organization.id,r.actorId);if(!n||n.status!=="active"||n.roleTemplate==="owner"||!r.emailVerifiedAt||!r.email)return!1;let i=r.email.split("@")[1]?.toLowerCase();return e.listOidcProviders(t.organization.id).some((o)=>o.enforceSso&&!!i&&o.allowedDomains.includes(i))}function eT(e){return e.replace(/[&<>"']/g,(t)=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function oy(e=!1,t=[]){let r=e?"/serverless":"/",n=t.map((o)=>`<a class="sso-button" href="/auth/oidc/${encodeURIComponent(o.slug)}/start?return=${encodeURIComponent(r)}">Continue with ${eT(o.name)}</a>`).join("");return`<!doctype html>
|
|
152
|
+
<html lang="en">
|
|
153
|
+
<head>
|
|
154
|
+
<meta charset="UTF-8">
|
|
155
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
156
|
+
<title>Sign in · ts-cloud</title>
|
|
157
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E">
|
|
158
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
159
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
160
|
+
<style>${`
|
|
161
|
+
:root {
|
|
162
|
+
--bg: #0a0e15; --bg2: #0b0f18; --panel: rgba(255,255,255,0.03); --panel-br: rgba(255,255,255,0.072);
|
|
163
|
+
--txt: #e9edf5; --txt2: #94a1b8; --txt3: #5a6577;
|
|
164
|
+
--accent: #5a8be0; --accent-ink: #061019;
|
|
165
|
+
--bad: #f0736e; --badbg: rgba(240,115,110,0.11);
|
|
166
|
+
}
|
|
167
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
168
|
+
html { background: var(--bg); min-height: 100%; }
|
|
169
|
+
body {
|
|
170
|
+
font-family: 'Inter', system-ui, sans-serif; color: var(--txt); min-height: 100vh;
|
|
171
|
+
background:
|
|
172
|
+
radial-gradient(900px 460px at 88% -8%, rgba(90,139,224,0.06), transparent 62%),
|
|
173
|
+
linear-gradient(175deg, var(--bg), var(--bg2));
|
|
174
|
+
-webkit-font-smoothing: antialiased;
|
|
175
|
+
display: grid; place-items: center; padding: 24px;
|
|
176
|
+
}
|
|
177
|
+
.card {
|
|
178
|
+
width: 100%; max-width: 380px;
|
|
179
|
+
background: var(--panel); border: 1px solid var(--panel-br); border-radius: 16px;
|
|
180
|
+
padding: 32px; backdrop-filter: blur(6px);
|
|
181
|
+
animation: rise .5s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
182
|
+
}
|
|
183
|
+
@keyframes rise { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
|
|
184
|
+
@media (prefers-reduced-motion: reduce) { .card { animation: none } }
|
|
185
|
+
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
|
|
186
|
+
.brand .dot { width: 20px; height: 20px; border-radius: 6px; background: var(--accent); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); }
|
|
187
|
+
h1 { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; margin-top: 22px; }
|
|
188
|
+
.sub { color: var(--txt2); font-size: 13.5px; margin-top: 5px; line-height: 1.5; }
|
|
189
|
+
form { margin-top: 24px; display: grid; gap: 14px; }
|
|
190
|
+
.field { display: flex; flex-direction: column; gap: 7px; }
|
|
191
|
+
label { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; }
|
|
192
|
+
input {
|
|
193
|
+
width: 100%; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px;
|
|
194
|
+
padding: 10px 12px; color: var(--txt); font-family: inherit; font-size: 14px;
|
|
195
|
+
}
|
|
196
|
+
input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(90,139,224,0.12); }
|
|
197
|
+
button {
|
|
198
|
+
margin-top: 4px; background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 10px;
|
|
199
|
+
padding: 11px 16px; font-weight: 700; font-size: 13.5px; cursor: pointer; font-family: inherit;
|
|
200
|
+
transition: filter .12s, transform .12s;
|
|
201
|
+
}
|
|
202
|
+
button:hover { filter: brightness(1.06); }
|
|
203
|
+
button:active { transform: translateY(1px); }
|
|
204
|
+
button[disabled] { opacity: 0.6; cursor: default; }
|
|
205
|
+
.msg {
|
|
206
|
+
display: none; margin-top: 14px; padding: 10px 12px; border-radius: 10px;
|
|
207
|
+
background: var(--badbg); border: 1px solid rgba(240,115,110,0.22); color: var(--bad);
|
|
208
|
+
font-size: 13px; line-height: 1.45;
|
|
209
|
+
}
|
|
210
|
+
.msg.shown { display: block; }
|
|
211
|
+
.hidden { display: none !important; }
|
|
212
|
+
.note { color: var(--txt3); font-size: 12px; margin-top: 20px; line-height: 1.5; }
|
|
213
|
+
.note code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--txt2); }
|
|
214
|
+
a { color: var(--accent); text-decoration: none; }
|
|
215
|
+
a:hover { text-decoration: underline; }
|
|
216
|
+
.sso { display: grid; gap: 10px; margin-top: 22px; }
|
|
217
|
+
.sso-button { display: block; border: 1px solid var(--panel-br); border-radius: 10px; padding: 11px 14px; color: var(--txt); text-align: center; font-size: 13.5px; font-weight: 700; background: rgba(255,255,255,0.04); }
|
|
218
|
+
.sso-button:hover { border-color: var(--accent); text-decoration: none; }
|
|
219
|
+
.separator { display: flex; align-items: center; gap: 10px; margin: 18px 0 -6px; color: var(--txt3); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; }
|
|
220
|
+
.separator::before, .separator::after { content: ''; height: 1px; flex: 1; background: var(--panel-br); }
|
|
221
|
+
`}</style>
|
|
222
|
+
</head>
|
|
223
|
+
<body>
|
|
224
|
+
<main class="card">
|
|
225
|
+
<div class="brand"><span class="dot"></span> ts-cloud</div>
|
|
226
|
+
<h1>Sign in</h1>
|
|
227
|
+
<p class="sub">Manage the sites you have been given access to.</p>
|
|
228
|
+
|
|
229
|
+
${t.length>0?`<div class="sso" aria-label="Single sign-on">${n}</div><div class="separator"><span>or use local recovery</span></div>`:""}
|
|
230
|
+
|
|
231
|
+
<form id="login" autocomplete="on">
|
|
232
|
+
<div class="field">
|
|
233
|
+
<label for="username">Username</label>
|
|
234
|
+
<input id="username" name="username" autocomplete="username" required autofocus>
|
|
235
|
+
</div>
|
|
236
|
+
<div class="hidden field" id="mfa-field">
|
|
237
|
+
<label for="mfa-code">Authenticator or recovery code</label>
|
|
238
|
+
<input id="mfa-code" name="mfa-code" autocomplete="one-time-code">
|
|
239
|
+
</div>
|
|
240
|
+
<div class="field">
|
|
241
|
+
<label for="password">Password</label>
|
|
242
|
+
<input id="password" name="password" type="password" autocomplete="current-password" required>
|
|
243
|
+
</div>
|
|
244
|
+
<button type="submit" id="submit">Sign in</button>
|
|
245
|
+
</form>
|
|
246
|
+
|
|
247
|
+
<p class="msg" id="msg" role="alert" aria-live="polite"></p>
|
|
248
|
+
<p class="note"><a href="/forgot-password">Forgot your password?</a></p>
|
|
249
|
+
</main>
|
|
250
|
+
|
|
251
|
+
<script>
|
|
252
|
+
const form = document.getElementById('login')
|
|
253
|
+
const msg = document.getElementById('msg')
|
|
254
|
+
const submit = document.getElementById('submit')
|
|
255
|
+
const mfaField = document.getElementById('mfa-field')
|
|
256
|
+
const mfaCode = document.getElementById('mfa-code')
|
|
257
|
+
let challengeToken = ''
|
|
258
|
+
|
|
259
|
+
if (new URLSearchParams(location.search).has('sso_error')) {
|
|
260
|
+
msg.textContent = 'Single sign-on could not be completed. Try again or use the local recovery path.'
|
|
261
|
+
msg.classList.add('shown')
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
form.addEventListener('submit', async (event) => {
|
|
265
|
+
event.preventDefault()
|
|
266
|
+
msg.classList.remove('shown')
|
|
267
|
+
submit.disabled = true
|
|
268
|
+
submit.textContent = 'Signing in...'
|
|
269
|
+
try {
|
|
270
|
+
const res = await fetch(challengeToken ? '/api/auth/mfa/complete' : '/api/login', {
|
|
271
|
+
method: 'POST',
|
|
272
|
+
headers: { 'content-type': 'application/json' },
|
|
273
|
+
body: JSON.stringify(challengeToken
|
|
274
|
+
? { challengeToken, code: mfaCode.value }
|
|
275
|
+
: { username: document.getElementById('username').value, password: document.getElementById('password').value }),
|
|
276
|
+
})
|
|
277
|
+
const body = await res.json().catch(() => ({}))
|
|
278
|
+
if (!res.ok || !body.ok) throw new Error(body.error || 'Could not sign in.')
|
|
279
|
+
if (body.mfaRequired) {
|
|
280
|
+
challengeToken = body.challengeToken
|
|
281
|
+
mfaField.classList.remove('hidden')
|
|
282
|
+
mfaCode.required = true
|
|
283
|
+
document.getElementById('username').readOnly = true
|
|
284
|
+
document.getElementById('password').readOnly = true
|
|
285
|
+
submit.disabled = false
|
|
286
|
+
submit.textContent = 'Verify and sign in'
|
|
287
|
+
mfaCode.focus()
|
|
288
|
+
return
|
|
289
|
+
}
|
|
290
|
+
location.href = ${JSON.stringify(r)}
|
|
291
|
+
} catch (error) {
|
|
292
|
+
msg.textContent = (error && error.message) || String(error)
|
|
293
|
+
msg.classList.add('shown')
|
|
294
|
+
submit.disabled = false
|
|
295
|
+
submit.textContent = 'Sign in'
|
|
296
|
+
if (challengeToken) {
|
|
297
|
+
mfaCode.value = ''
|
|
298
|
+
mfaCode.focus()
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
document.getElementById('password').value = ''
|
|
302
|
+
document.getElementById('password').focus()
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
</script>
|
|
307
|
+
</body>
|
|
308
|
+
</html>`}function sy(e){let t=e==="reset";return`<!doctype html>
|
|
309
|
+
<html lang="en">
|
|
310
|
+
<head>
|
|
311
|
+
<meta charset="UTF-8">
|
|
312
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
313
|
+
<title>${t?"Choose a new password":"Recover your account"} · ts-cloud</title>
|
|
314
|
+
<style>${`
|
|
315
|
+
:root {
|
|
316
|
+
--bg: #0a0e15; --bg2: #0b0f18; --panel: rgba(255,255,255,0.03); --panel-br: rgba(255,255,255,0.072);
|
|
317
|
+
--txt: #e9edf5; --txt2: #94a1b8; --txt3: #5a6577;
|
|
318
|
+
--accent: #5a8be0; --accent-ink: #061019;
|
|
319
|
+
--bad: #f0736e; --badbg: rgba(240,115,110,0.11);
|
|
320
|
+
}
|
|
321
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
322
|
+
html { background: var(--bg); min-height: 100%; }
|
|
323
|
+
body {
|
|
324
|
+
font-family: 'Inter', system-ui, sans-serif; color: var(--txt); min-height: 100vh;
|
|
325
|
+
background:
|
|
326
|
+
radial-gradient(900px 460px at 88% -8%, rgba(90,139,224,0.06), transparent 62%),
|
|
327
|
+
linear-gradient(175deg, var(--bg), var(--bg2));
|
|
328
|
+
-webkit-font-smoothing: antialiased;
|
|
329
|
+
display: grid; place-items: center; padding: 24px;
|
|
330
|
+
}
|
|
331
|
+
.card {
|
|
332
|
+
width: 100%; max-width: 380px;
|
|
333
|
+
background: var(--panel); border: 1px solid var(--panel-br); border-radius: 16px;
|
|
334
|
+
padding: 32px; backdrop-filter: blur(6px);
|
|
335
|
+
animation: rise .5s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
336
|
+
}
|
|
337
|
+
@keyframes rise { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
|
|
338
|
+
@media (prefers-reduced-motion: reduce) { .card { animation: none } }
|
|
339
|
+
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
|
|
340
|
+
.brand .dot { width: 20px; height: 20px; border-radius: 6px; background: var(--accent); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); }
|
|
341
|
+
h1 { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; margin-top: 22px; }
|
|
342
|
+
.sub { color: var(--txt2); font-size: 13.5px; margin-top: 5px; line-height: 1.5; }
|
|
343
|
+
form { margin-top: 24px; display: grid; gap: 14px; }
|
|
344
|
+
.field { display: flex; flex-direction: column; gap: 7px; }
|
|
345
|
+
label { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; }
|
|
346
|
+
input {
|
|
347
|
+
width: 100%; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px;
|
|
348
|
+
padding: 10px 12px; color: var(--txt); font-family: inherit; font-size: 14px;
|
|
349
|
+
}
|
|
350
|
+
input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(90,139,224,0.12); }
|
|
351
|
+
button {
|
|
352
|
+
margin-top: 4px; background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 10px;
|
|
353
|
+
padding: 11px 16px; font-weight: 700; font-size: 13.5px; cursor: pointer; font-family: inherit;
|
|
354
|
+
transition: filter .12s, transform .12s;
|
|
355
|
+
}
|
|
356
|
+
button:hover { filter: brightness(1.06); }
|
|
357
|
+
button:active { transform: translateY(1px); }
|
|
358
|
+
button[disabled] { opacity: 0.6; cursor: default; }
|
|
359
|
+
.msg {
|
|
360
|
+
display: none; margin-top: 14px; padding: 10px 12px; border-radius: 10px;
|
|
361
|
+
background: var(--badbg); border: 1px solid rgba(240,115,110,0.22); color: var(--bad);
|
|
362
|
+
font-size: 13px; line-height: 1.45;
|
|
363
|
+
}
|
|
364
|
+
.msg.shown { display: block; }
|
|
365
|
+
.hidden { display: none !important; }
|
|
366
|
+
.note { color: var(--txt3); font-size: 12px; margin-top: 20px; line-height: 1.5; }
|
|
367
|
+
.note code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--txt2); }
|
|
368
|
+
a { color: var(--accent); text-decoration: none; }
|
|
369
|
+
a:hover { text-decoration: underline; }
|
|
370
|
+
.sso { display: grid; gap: 10px; margin-top: 22px; }
|
|
371
|
+
.sso-button { display: block; border: 1px solid var(--panel-br); border-radius: 10px; padding: 11px 14px; color: var(--txt); text-align: center; font-size: 13.5px; font-weight: 700; background: rgba(255,255,255,0.04); }
|
|
372
|
+
.sso-button:hover { border-color: var(--accent); text-decoration: none; }
|
|
373
|
+
.separator { display: flex; align-items: center; gap: 10px; margin: 18px 0 -6px; color: var(--txt3); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; }
|
|
374
|
+
.separator::before, .separator::after { content: ''; height: 1px; flex: 1; background: var(--panel-br); }
|
|
375
|
+
`}</style>
|
|
376
|
+
</head>
|
|
377
|
+
<body>
|
|
378
|
+
<main class="card">
|
|
379
|
+
<div class="brand"><span class="dot"></span> ts-cloud</div>
|
|
380
|
+
<h1>${t?"Choose a new password":"Recover your account"}</h1>
|
|
381
|
+
<p class="sub">${t?"This one-time link expires after one hour.":"Enter your username or verified email. The response is the same whether or not an account exists."}</p>
|
|
382
|
+
<form id="recovery" autocomplete="on">
|
|
383
|
+
${t?'<div class="field"><label for="password">New password</label><input id="password" name="password" type="password" autocomplete="new-password" minlength="12" required></div><div class="field"><label for="confirmation">Confirm new password</label><input id="confirmation" name="confirmation" type="password" autocomplete="new-password" minlength="12" required></div>':'<div class="field"><label for="identifier">Username or email</label><input id="identifier" name="identifier" autocomplete="username" required autofocus></div>'}
|
|
384
|
+
<button type="submit" id="submit">${t?"Change password":"Send reset link"}</button>
|
|
385
|
+
</form>
|
|
386
|
+
<p class="msg" id="msg" role="status" aria-live="polite"></p>
|
|
387
|
+
<p class="note"><a href="/login">Return to sign in</a></p>
|
|
388
|
+
</main>
|
|
389
|
+
<script>
|
|
390
|
+
const form = document.getElementById('recovery')
|
|
391
|
+
const msg = document.getElementById('msg')
|
|
392
|
+
const submit = document.getElementById('submit')
|
|
393
|
+
const reset = ${JSON.stringify(t)}
|
|
394
|
+
const token = new URLSearchParams(location.search).get('token') || ''
|
|
395
|
+
if (reset && !token) {
|
|
396
|
+
msg.textContent = 'This reset link is missing its token. Request a new link.'
|
|
397
|
+
msg.classList.add('shown')
|
|
398
|
+
submit.disabled = true
|
|
399
|
+
}
|
|
400
|
+
form.addEventListener('submit', async (event) => {
|
|
401
|
+
event.preventDefault()
|
|
402
|
+
if (reset && document.getElementById('password').value !== document.getElementById('confirmation').value) {
|
|
403
|
+
msg.textContent = 'The passwords do not match.'
|
|
404
|
+
msg.classList.add('shown')
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
submit.disabled = true
|
|
408
|
+
msg.textContent = reset ? 'Changing password…' : 'Requesting reset link…'
|
|
409
|
+
msg.classList.add('shown')
|
|
410
|
+
const response = await fetch(reset ? '/api/auth/password-reset/complete' : '/api/auth/password-reset/request', {
|
|
411
|
+
method: 'POST',
|
|
412
|
+
headers: { 'content-type': 'application/json' },
|
|
413
|
+
body: JSON.stringify(reset
|
|
414
|
+
? { token, password: document.getElementById('password').value }
|
|
415
|
+
: { identifier: document.getElementById('identifier').value }),
|
|
416
|
+
})
|
|
417
|
+
const result = await response.json().catch(() => ({}))
|
|
418
|
+
msg.textContent = result.message || result.error || 'The request could not be completed.'
|
|
419
|
+
if (!response.ok) {
|
|
420
|
+
submit.disabled = false
|
|
421
|
+
return
|
|
422
|
+
}
|
|
423
|
+
if (reset)
|
|
424
|
+
setTimeout(() => location.assign('/login'), 1200)
|
|
425
|
+
})
|
|
426
|
+
</script>
|
|
427
|
+
</body>
|
|
428
|
+
</html>`}var tT=["restart","reload","start","stop","enable","disable"],ay=65536;function ra(e){return e.length<=ay?e:`${e.slice(0,ay)}
|
|
429
|
+
|
|
430
|
+
[output truncated]`}function rT(e){return/^[A-Za-z0-9_.@:-]+$/.test(e)}function Vl(e){return/^[A-Za-z0-9_-]+$/.test(e)}function nT(e){return e.charAt(0).toUpperCase()+e.slice(1)}function kr(e,t){let r=[],n=t.servicesDetail??t.services??[];for(let s of n){let c=String(s?.name??"");if(!c||!rT(c))continue;for(let l of tT)r.push({id:`${l}:${c}`,label:`${nT(l)} ${c}`,group:"service",target:c,mutates:!0,confirm:c,danger:l==="stop"||l==="disable"})}for(let[s,c]of Object.entries(e.sites??{})){if(!c||!Vl(s))continue;let l=P(c);if(l==="server-app"||l==="server-php")r.push({id:`rollback:${s}`,label:`Rollback ${s}`,group:"deploy",target:s,mutates:!0,confirm:s,danger:!0})}let i=new Set;for(let s of t.workers??[]){let c=String(s?.name??"").split(":")[0];if(c&&Vl(c))i.add(c)}for(let s of i)r.push({id:`worker:restart:${s}`,label:`Restart workers (${s})`,group:"worker",target:s,mutates:!0,confirm:s});for(let[s,c]of Object.entries(e.sites??{})){if(!c||!Vl(s))continue;if(c.scheduler||c.schedule){let l=Wr(c)==="laravel";r.push({id:`scheduler:run:${s}`,label:`${l?"Run":"Restart"} scheduler (${s})`,group:"scheduler",target:s,mutates:!0,confirm:s})}}if(e.infrastructure?.compute?.backups?.enabled){if(r.push({id:"backup:run",label:"Run backup now",group:"backup",target:"backup",mutates:!0,confirm:"backup"}),C(e))r.push({id:"backup:restore",label:"Restore latest DB backup",group:"backup",target:"database",mutates:!0,confirm:"restore",danger:!0})}return r}function xn(e,t,r){return kr(t,r).find((n)=>n.id===e)}function iT(e,t){let r=e==="enable"||e==="disable"?`systemctl is-enabled ${t} 2>/dev/null || true`:`systemctl is-active ${t} 2>/dev/null || true`;return["set -o pipefail",`systemctl ${e} ${t}`,r]}function oT(){return`eval "$(cd ${M} && pantry env 2>/dev/null)"`}function dy(e,t,r){let n=`${W(e,t)}/current`;return["set -uo pipefail",`[ -d ${n} ] || { echo "site ${t} has no current release" >&2; exit 1; }`,`cd ${n} && ${oT()} && php artisan ${r}`]}function sT(e,t,r){if(e==="laravel")return dy(t,r,"queue:restart");let n=`${t}-${r}-queue-*.service`;return["set -uo pipefail",`units=$(systemctl list-units --type=service --all --no-legend '${n}' 2>/dev/null | awk '{print $1}')`,`[ -n "$units" ] || { echo "no queue-worker units found for ${r} (${n})" >&2; exit 1; }`,"systemctl restart $units",`systemctl --no-legend --type=service list-units '${n}' 2>/dev/null || true`]}function aT(e,t,r){if(e==="laravel")return dy(t,r,"schedule:run");let n=`${t}-${r}-scheduler.service`;return["set -uo pipefail",`systemctl restart ${n}`,`systemctl is-active ${n} 2>/dev/null || true`]}function cT(){return["set -uo pipefail",`[ -x ${Gr} ] || { echo "scheduled backups are not provisioned on this server" >&2; exit 1; }`,Gr]}function cy(e,t,r){return{operation:e,command:t,ok:r.success,stdout:ra(r.perInstance?.[0]?.output??""),stderr:ra(r.perInstance?.[0]?.error??r.error??"")}}async function Dr(e,t,r,n={}){let i=e.project.slug,o;try{o=x({config:e})}catch(E){return{operation:r.id,ok:!1,error:`Could not initialize the cloud driver: ${E?.message??E}`}}let s={driver:o,slug:i,environment:t,role:"app"};if(r.group==="deploy"){let E=n.to&&/^[A-Za-z0-9._-]+$/.test(n.to)?n.to:void 0,k=await Xo(s,{siteName:r.target,to:E});return cy(r.id,`rollback ${r.target}${E?` → ${E}`:""}`,k)}if(r.id==="backup:restore"){let E=await Qo(s,{database:C(e)});return cy(r.id,"db restore",E)}let c=await o.findComputeTargets({slug:i,environment:t,role:"app"});if(!c.length)return{operation:r.id,ok:!1,error:"No app server target was found for this environment."};let l,a;if(r.group==="service"){let[E,...k]=r.id.split(":");l=iT(E,k.join(":")),a=`systemctl ${E} ${r.target}`}else if(r.group==="worker"){let E=Wr(e.sites?.[r.target]??{});l=sT(E,i,r.target),a=E==="laravel"?`queue:restart (${r.target})`:`restart queue units (${r.target})`}else if(r.group==="scheduler"){let E=Wr(e.sites?.[r.target]??{});l=aT(E,i,r.target),a=E==="laravel"?`schedule:run (${r.target})`:`restart scheduler (${r.target})`}else if(r.id==="backup:run")l=cT(),a="ts-cloud backup";else return{operation:r.id,ok:!1,error:"Unknown operation."};let m=await o.runRemoteDeploy({targets:[c[0]],commands:l,comment:`ts-cloud dashboard:${r.id}`,tags:{Project:i,Environment:t,Role:"app"}});return{operation:r.id,command:a,ok:m.success,stdout:ra(m.perInstance?.[0]?.output??""),stderr:ra(m.perInstance?.[0]?.error??m.error??"")}}async function Xt(e,t,r){let n=r.trim();if(!n)return{operation:"command",ok:!1,error:"A command is required."};let i;try{i=x({config:e})}catch(l){return{operation:"command",ok:!1,error:`Could not initialize the cloud driver: ${l?.message??l}`}}let o=e.project.slug,s=await i.findComputeTargets({slug:o,environment:t,role:"app"});if(!s.length)return{operation:"command",ok:!1,error:"No app server target was found for this environment."};let c=await i.runRemoteDeploy({targets:[s[0]],commands:["set -o pipefail",n],comment:"ts-cloud dashboard:command",tags:{Project:o,Environment:t,Role:"app"}});return{operation:"command",command:n,ok:c.success,stdout:ra(c.perInstance?.[0]?.output??""),stderr:ra(c.perInstance?.[0]?.error??c.error??"")}}var dT=[{id:"server.overview",path:"/",label:"Dashboard",group:"overview",modes:["server"],adminOnly:!0,legacyPaths:["/server"]},{id:"server.activity",path:"/server/activity",label:"Activity",group:"overview",modes:["server"],adminOnly:!0,legacyPaths:["/activity"]},{id:"services.list",path:"/server/sites",label:"Services",group:"applications",modes:["server"],adminOnly:!1,legacyPaths:["/sites","/services"]},{id:"deployments.list",path:"/server/deployments",label:"Deployments",group:"applications",modes:["server"],adminOnly:!1,legacyPaths:["/deployments"]},{id:"logs.list",path:"/server/logs",label:"Logs",group:"applications",modes:["server"],adminOnly:!1,legacyPaths:["/logs"]},{id:"sources.integrations",path:"/integrations",label:"Git integrations",group:"applications",modes:["server","serverless"],adminOnly:!1},{id:"applications.create",path:"/applications/new",label:"Create application",group:"applications",modes:["server","serverless"],adminOnly:!1},{id:"applications.compose",path:"/applications/compose",label:"Compose applications",group:"applications",modes:["server"],adminOnly:!1},{id:"operations.queue",path:"/operations/queue",label:"Deployment queue",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"operations.previews",path:"/operations/previews",label:"Preview environments",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"operations.releases",path:"/operations/releases",label:"Releases & promotion",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"runtime.workloads",path:"/operations/workloads",label:"Workloads",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"observability.overview",path:"/operations/observability",label:"Observability",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"alerts.overview",path:"/operations/alerts",label:"Alerts & health",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"spend.overview",path:"/operations/spend",label:"Spend & budgets",group:"operations",modes:["server","serverless"],adminOnly:!1},{id:"automation.jobs",path:"/operations/jobs",label:"Workers & schedules",group:"operations",modes:["server","serverless"],adminOnly:!1,legacyPaths:["/server/workers","/serverless/scheduler"]},{id:"configuration.entries",path:"/operations/configuration",label:"Environment & secrets",group:"operations",modes:["server","serverless"],adminOnly:!1,legacyPaths:["/serverless/secrets"]},{id:"metrics.overview",path:"/server/metrics",label:"Metrics",group:"operations",modes:["server"],adminOnly:!0},{id:"runtime.services",path:"/server/services",label:"Runtime services",group:"operations",modes:["server"],adminOnly:!0},{id:"backups.list",path:"/data/backups",label:"Backups & recovery",group:"operations",modes:["server","serverless"],adminOnly:!1,legacyPaths:["/server/backups"]},{id:"volumes.list",path:"/data/volumes",label:"Persistent volumes",group:"operations",modes:["server","serverless"],adminOnly:!1,legacyPaths:[]},{id:"fleet.list",path:"/server/fleet",label:"Fleet inventory",group:"operations",modes:["server"],adminOnly:!1,legacyPaths:[]},{id:"operations.run",path:"/server/actions",label:"Run operations",group:"operations",modes:["server"],adminOnly:!0},{id:"infrastructure.topology",path:"/infrastructure/topology",label:"Infrastructure map",group:"infrastructure",modes:["server","serverless"],adminOnly:!0,legacyPaths:["/topology"]},{id:"data.services",path:"/data/services",label:"Data services",group:"infrastructure",modes:["server","serverless"],adminOnly:!1,legacyPaths:["/database","/databases","/server/database","/serverless/data"]},{id:"network.firewall",path:"/server/firewall",label:"Network & firewall",group:"infrastructure",modes:["server"],adminOnly:!0},{id:"security.posture",path:"/security",label:"Security posture",group:"infrastructure",modes:["server","serverless"],adminOnly:!1,legacyPaths:["/server/security"]},{id:"access.ssh",path:"/server/ssh-keys",label:"SSH keys",group:"infrastructure",modes:["server"],adminOnly:!0},{id:"runtime.terminal",path:"/server/terminal",label:"Terminal",group:"infrastructure",modes:["server"],adminOnly:!0},{id:"organization.people",path:"/server/team",label:"People & access",group:"organization",modes:["server","serverless"],adminOnly:!0,legacyPaths:["/team"]},{id:"organization.automation",path:"/account/automation",label:"API & automation",group:"organization",modes:["server","serverless"],adminOnly:!0},{id:"serverless.overview",path:"/serverless",label:"Dashboard",group:"overview",modes:["serverless"],adminOnly:!0},{id:"serverless.deployments",path:"/serverless/deployments",label:"Deployments",group:"overview",modes:["serverless"],adminOnly:!0},{id:"serverless.logs",path:"/serverless/logs",label:"Logs",group:"overview",modes:["serverless"],adminOnly:!0},{id:"serverless.metrics",path:"/serverless/metrics",label:"Metrics",group:"overview",modes:["serverless"],adminOnly:!0},{id:"serverless.traces",path:"/serverless/traces",label:"Traces",group:"overview",modes:["serverless"],adminOnly:!0},{id:"serverless.functions",path:"/serverless/functions",label:"Functions",group:"compute-data",modes:["serverless"],adminOnly:!0},{id:"serverless.queues",path:"/serverless/queues",label:"Queues",group:"compute-data",modes:["serverless"],adminOnly:!0},{id:"serverless.assets",path:"/serverless/assets",label:"Assets",group:"compute-data",modes:["serverless"],adminOnly:!0},{id:"serverless.network",path:"/serverless/firewall",label:"Network",group:"settings",modes:["serverless"],adminOnly:!0},{id:"serverless.alerts",path:"/serverless/alarms",label:"Alerts",group:"settings",modes:["serverless"],adminOnly:!0},{id:"serverless.cost",path:"/serverless/cost",label:"Costs",group:"settings",modes:["serverless"],adminOnly:!0}],uT=new Map(dT.flatMap((e)=>(e.legacyPaths??[]).map((t)=>[t,e.path])));function uy(e){return uT.get(e)}function lT(e,t){return[`${e}-${t}`,`${e}-${t}-queues`,`${e}-${t}-daemons`]}function ly(e,t,r){return r.some((n)=>lT(t,n).includes(e))}function ql(e,t){let{user:r,slug:n}=t;if(r.role==="admin")return e;let i=(e.sites??[]).map((q)=>q.name).filter(Boolean),o=_l(r,i),s=new Set(o),c=(e.sites??[]).filter((q)=>s.has(q.name)),l=(e.sitesDetail??[]).filter((q)=>s.has(q.name)),a=new Set(l.map((q)=>q.domain).filter(Boolean)),m=(e.serverDeploymentsDetail??e.serverDeployments??[]).filter((q)=>s.has(q.site)),E=(e.serverLogs??[]).filter((q)=>ly(q.source,n,o)),k=(e.security?.tlsCertificates??[]).filter((q)=>a.has(q.domain)),O=(e.activity??[]).filter((q)=>{if(q.type==="deploy")return o.some((G)=>String(q.title??"").startsWith(`${G} `));if(q.type==="log")return ly(String(q.title??"").split(" ")[0],n,o);return!1});return{mode:e.mode,environment:e.environment,environments:e.environments,scoped:!0,server:{name:""},sites:c,sitesDetail:l,workers:(e.workers??[]).filter((q)=>s.has(q.site)),serverDeployments:m.slice(0,5),serverDeploymentsDetail:m.slice(0,50),deploymentsEmptyReason:m.length?void 0:"No deployments have been recorded for your sites yet.",serverLogs:E,serverLogsEmptyReason:E.length?void 0:"No recent log entries for your sites.",security:{tlsCertificates:k,ports:[],firewall:null,authEvents:[]},diagnostics:(e.diagnostics??[]).filter((q)=>["Route conflicts","TLS certificates"].includes(q.name)),activity:O}}function py(e,t){if(t.role==="admin")return e;let r=new Set(_l(t,Object.keys(e.sites??{})));return{project:{name:e.project?.name},environment:e.environment,environments:e.environments,sites:Object.fromEntries(Object.entries(e.sites??{}).filter(([n])=>r.has(n)))}}var pT=new Set(["name","ssl","env","redirects","aliases","domain","path"]),gy={build:"build runs as a shell command on the server",start:"start runs as a shell command on the server",root:"root is a filesystem path on the shared server",port:"ports are allocated by the server owner",type:"the deploy type is set by the server owner",php:"the PHP runtime is set by the server owner"};function fy(e){let t=Object.keys(e).filter((i)=>e[i]!==void 0),r=t.filter((i)=>(i in gy));if(r.length)return{ok:!1,error:`Only the server owner can change ${r.map((o)=>`${o} (${gy[o]})`).join(", ")}.`};let n=t.filter((i)=>!pT.has(i));if(n.length)return{ok:!1,error:`Only the server owner can change ${n.join(", ")}.`};return{ok:!0}}function bd(e){return String(e??"").trim().toLowerCase().replace(/\.$/,"")}function my(e){let t=String(e??"/").trim();if(!t||t==="/")return"/";return(t.startsWith("/")?t:`/${t}`).replace(/\/+$/,"")||"/"}function gT(e){let t=[bd(e?.domain)];if(Array.isArray(e?.aliases))t.push(...e.aliases.map(bd));return t.filter(Boolean)}function hy({siteName:e,body:t,sites:r,ownSites:n}){let i=r[e]??{},o=new Set(n),s=new Set;if(t.domain!==void 0)s.add(bd(t.domain));if(Array.isArray(t.aliases))for(let l of t.aliases)s.add(bd(l));if(s.delete(""),s.size===0)return{ok:!0};let c=my(t.path!==void 0?t.path:i.path);for(let[l,a]of Object.entries(r)){if(l===e||o.has(l))continue;let m=my(a?.path);for(let E of gT(a)){if(!s.has(E))continue;if(m===c)return{ok:!1,error:`${E}${c==="/"?"":c} is already served by another site on this server.`}}}return{ok:!0}}class Ba{maxAttempts;lockoutMs;windowMs;attempts=new Map;constructor(e=8,t=900000,r=900000){this.maxAttempts=e;this.lockoutMs=t;this.windowMs=r}key(e,t){return`${e.trim().toLowerCase()}\x00${t}`}check(e,t,r=Date.now()){let n=this.attempts.get(this.key(e,t));if(!n?.until)return{allowed:!0};if(r>=n.until)return this.attempts.delete(this.key(e,t)),{allowed:!0};return{allowed:!1,retryAfterSeconds:Math.ceil((n.until-r)/1000)}}recordFailure(e,t,r=Date.now()){let n=this.key(e,t),i=this.attempts.get(n),s=!i||r-i.last>this.windowMs?1:i.count+1,c={count:s,last:r};if(s>=this.maxAttempts)c.until=r+this.lockoutMs;this.attempts.set(n,c)}recordSuccess(e,t){this.attempts.delete(this.key(e,t))}prune(e=Date.now()){for(let[t,r]of this.attempts)if(r.until?e>=r.until:e-r.last>this.windowMs)this.attempts.delete(t)}get size(){return this.attempts.size}}var by=new Set([22,80,443]);function ja(e){return Number.isInteger(e)&&e>=1&&e<=65535}function hs(e){return[...new Set(e.filter((t)=>ja(t)&&!by.has(t)))].sort((t,r)=>t-r)}function Sy(e,t,r=[]){if(!ja(t))throw Error("Port must be an integer between 1 and 65535.");if(by.has(t))throw Error(`Port ${t} (SSH/HTTP/HTTPS) is always open and is not managed here.`);return wy({configText:e,ports:hs([...r,t])})}function vy(e,t,r=[]){return wy({configText:e,ports:hs(r.filter((n)=>n!==t))})}function yy(e,t,r,n,i){let o=e.slice(t,r),s=new RegExp(`\\b${n}\\s*:\\s*\\${i}`).exec(o);if(!s)return null;let c=t+s.index,l=e.indexOf(i,c);return{propStart:c,open:l,close:ei(e,l,i,i==="{"?"}":"]")}}function Jl(e){return`allowedPorts: [${e.join(", ")}]`}function wy(e){let{configText:t}=e,r=hs(e.ports),n=/\bcompute\s*:\s*{/.exec(t);if(!n)throw Error("Could not find infrastructure.compute in the cloud config.");let i=t.indexOf("{",n.index),o=ei(t,i,"{","}"),s=yy(t,i+1,o,"firewall","{");if(s){let m=yy(t,s.open+1,s.close,"allowedPorts","[");if(m){let q=m.propStart;while(q>0&&t[q-1]!==`
|
|
431
|
+
`&&/\s/.test(t[q-1]))q--;let G=t.slice(q,m.propStart);return`${t.slice(0,q)}${G}${Jl(r)}${t.slice(m.close+1)}`}let E=t.slice(0,s.close).trimEnd(),k=t.slice(s.close),O=E.endsWith(",")||E.endsWith("{")?"":",";return`${E}${O}
|
|
432
|
+
${Jl(r)},
|
|
433
|
+
${k}`}let c=t.slice(0,o).trimEnd(),l=t.slice(o),a=c.endsWith(",")||c.endsWith("{")?"":",";return`${c}${a}
|
|
434
|
+
firewall: {
|
|
435
|
+
enabled: true,
|
|
436
|
+
${Jl(r)},
|
|
437
|
+
},
|
|
438
|
+
${l}`}class Wl{client;region;constructor(e="us-east-1"){this.region=e,this.client=new u}async getTraceSummaries(e){let t={StartTime:Math.floor(e.startTime.getTime()/1000),EndTime:Math.floor(e.endTime.getTime()/1000),TimeRangeType:"Event",Sampling:!1};if(e.filterExpression)t.FilterExpression=e.filterExpression;if(e.nextToken)t.NextToken=e.nextToken;let r=await this.client.request({service:"xray",region:this.region,method:"POST",path:"/TraceSummaries",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});return{summaries:r?.TraceSummaries??[],nextToken:r?.NextToken}}async batchGetTraces(e){if(!e.length)return[];return(await this.client.request({service:"xray",region:this.region,method:"POST",path:"/Traces",headers:{"Content-Type":"application/json"},body:JSON.stringify({TraceIds:e.slice(0,5)})}))?.Traces??[]}}var Iy=65536;function tn(e){return e.length<=Iy?e:`${e.slice(0,Iy)}
|
|
439
|
+
|
|
440
|
+
[output truncated]`}function Gl(e,t){return e.environments?.[t]?.app}function Kl(e,t,r){let n=[],i=Gl(e,t);n.push({id:"redeploy",label:"Redeploy current build",group:"deploy",target:"app",mutates:!0,confirm:"redeploy"}),n.push({id:"rollback",label:"Roll back to previous build",group:"deploy",target:"app",mutates:!0,confirm:"rollback",danger:!0});let o=r.maintenance?.enabled;if(o!==!0)n.push({id:"maintenance:on",label:"Enable maintenance mode",group:"maintenance",target:"app",mutates:!0,confirm:"maintenance",danger:!0});if(o!==!1)n.push({id:"maintenance:off",label:"Disable maintenance mode",group:"maintenance",target:"app",mutates:!0,confirm:"live"});if(i?.assets||r.assetsInfo)n.push({id:"assets:invalidate",label:"Invalidate CDN cache",group:"assets",target:"assets",mutates:!0,confirm:"invalidate"});if(i?.database?.connection==="aurora-serverless")n.push({id:"db:scale",label:"Scale Aurora capacity",group:"database",target:"database",mutates:!0,confirm:"scale",inputs:[{name:"min",label:"Min ACUs",placeholder:String(i.database.minCapacity??0.5)},{name:"max",label:"Max ACUs",placeholder:String(i.database.maxCapacity??4)}]});for(let s of r.queues??[]){let c=String(s?.name??"").trim();if(c&&/^[A-Za-z0-9_-]+$/.test(c))n.push({id:`queue:purge:${c}`,label:`Purge queue (${c})`,group:"queue",target:c,mutates:!0,confirm:c,danger:!0})}return n}function Cy(e,t,r,n){return Kl(t,r,n).find((i)=>i.id===e)}async function mT(e,t,r){try{let n=new v(r),{Stacks:i}=await n.describeStacks({stackName:Pe(e,t)}),o={};for(let l of i?.[0]?.Outputs??[])if(l.OutputKey)o[l.OutputKey]=l.OutputValue??"";let s=o.AssetsCdnDomain;if(!s)return null;return(await new w(r).findDistributionByDomain(s))?.Id??null}catch{return null}}async function Ey(e,t,r,n={}){try{if(r.id==="redeploy")return await Zo(e,t),{operation:r.id,command:"serverless redeploy",ok:!0,stdout:"Redeploy complete."};if(r.id==="rollback")return await es(e,t),{operation:r.id,command:"serverless rollback",ok:!0,stdout:"Rollback complete."};if(r.id==="maintenance:on")return await zi(e,t,!0),{operation:r.id,command:"maintenance on",ok:!0,stdout:"Application is now in maintenance mode."};if(r.id==="maintenance:off")return await zi(e,t,!1),{operation:r.id,command:"maintenance off",ok:!0,stdout:"Application is live."};if(r.id==="db:scale"){let i=Number(n.min),o=Number(n.max);if(!Number.isFinite(i)||!Number.isFinite(o)||i<=0||o<i)return{operation:r.id,ok:!1,error:"Provide valid Aurora capacities (0 < min ≤ max)."};return await ts(e,t,i,o),{operation:r.id,command:`db:scale ${i}-${o} ACU`,ok:!0,stdout:`Scaling applied (${i}-${o} ACUs); takes effect shortly.`}}if(r.id==="assets:invalidate"){let i=await j(e,t),o=await mT(e,t,i.region);if(!o)return{operation:r.id,ok:!1,error:"Could not resolve the asset CloudFront distribution for this environment."};let c=await new w(i.region).invalidateAll(o);return{operation:r.id,command:`cloudfront invalidate ${o} /*`,ok:!0,stdout:`Invalidation ${c?.Id??"created"} for ${o} (/*).`}}if(r.group==="queue"&&r.id.startsWith("queue:purge:")){let i=r.target,o=await j(e,t),s=new F(o.region),c=`${o.slug}-${t}-${i}`,{QueueUrl:l}=await s.getQueueUrl(c);return await s.purgeQueue(l),{operation:r.id,command:`sqs purge ${c}`,ok:!0,stdout:`Purged queue ${c}.`}}return{operation:r.id,ok:!1,error:"Unknown or unavailable serverless operation."}}catch(i){return{operation:r.id,ok:!1,error:tn(i?.message??String(i))}}}async function Ty(e,t,r){let n=r.trim();if(!n)return{operation:"command",ok:!1,error:"A command is required."};try{let i=await _t(e,t,n);return{operation:"command",command:n,ok:!0,stdout:tn(i||"(no output)")}}catch(i){return{operation:"command",command:n,ok:!1,error:tn(i?.message??String(i))}}}var Ql="No dead-letter queue is provisioned for this environment.";async function Yl(e,t,r){try{let{QueueUrl:n}=await e.getQueueUrl(`${t}-${r}-dlq`);return n}catch{return null}}async function Ay(e,t,r=10){try{let n=await j(e,t),i=new F(n.region),o=await Yl(i,n.slug,t);if(!o)return{ok:!1,messages:[],error:Ql};return{ok:!0,messages:((await i.receiveMessages({queueUrl:o,maxMessages:Math.min(10,Math.max(1,r)),waitTimeSeconds:1,visibilityTimeout:2})).Messages??[]).map((l)=>({id:l.MessageId,receiptHandle:l.ReceiptHandle,body:tn(String(l.Body??""))}))}}catch(n){return{ok:!1,messages:[],error:tn(n?.message??String(n))}}}async function ky(e,t,r={}){try{let n=await j(e,t),i=Gl(e,t),s=(i?jt(i,n.slug,t):[]).map((O)=>O.name.replace(`${n.slug}-${t}-`,"")),c=r.targetQueue&&s.includes(r.targetQueue)?r.targetQueue:s[0];if(!c)return{operation:"dlq:redrive",ok:!1,error:"No source queue is configured to redrive into."};let l=new F(n.region),a=await Yl(l,n.slug,t);if(!a)return{operation:"dlq:redrive",ok:!1,error:Ql};let{QueueUrl:m}=await l.getQueueUrl(`${n.slug}-${t}-${c}`),E=Math.min(50,Math.max(1,r.max??10)),k=0;while(k<E){let q=(await l.receiveMessages({queueUrl:a,maxMessages:Math.min(10,E-k),waitTimeSeconds:1,visibilityTimeout:30})).Messages??[];if(!q.length)break;for(let G of q)await l.sendMessage({queueUrl:m,messageBody:String(G.Body??"")}),await l.deleteMessage(a,G.ReceiptHandle),k++}return{operation:"dlq:redrive",command:`redrive → ${c}`,ok:!0,stdout:`Moved ${k} message(s) from the DLQ to ${c}.`}}catch(n){return{operation:"dlq:redrive",ok:!1,error:tn(n?.message??String(n))}}}async function Ry(e,t){try{let r=await j(e,t),n=new F(r.region),i=await Yl(n,r.slug,t);if(!i)return{operation:"dlq:purge",ok:!1,error:Ql};return await n.purgeQueue(i),{operation:"dlq:purge",command:"sqs purge dlq",ok:!0,stdout:"Dead-letter queue purged."}}catch(r){return{operation:"dlq:purge",ok:!1,error:tn(r?.message??String(r))}}}function Py(e,t){let r=Gl(e,t);if(!r?.secrets)return[];return Array.isArray(r.secrets)?r.secrets.map((n)=>({key:n.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),secretId:n})):Object.entries(r.secrets).map(([n,i])=>({key:n,secretId:String(i)}))}async function xy(e,t,r,n){if(!r.trim())return{operation:"secret:set",ok:!1,error:"A secret id is required."};try{let i=await j(e,t),o=new H(i.region);try{await o.putSecretValue({SecretId:r,SecretString:n})}catch{await o.createSecret({Name:r,SecretString:n})}return{operation:"secret:set",command:`secret set ${r}`,ok:!0,stdout:`Secret ${r} updated. Redeploy to apply it to the functions.`}}catch(i){return{operation:"secret:set",ok:!1,error:tn(i?.message??String(i))}}}async function Dy(e,t,r){if(!r.trim())return{operation:"secret:delete",ok:!1,error:"A secret id is required."};try{let n=await j(e,t);return await new H(n.region).deleteSecret({SecretId:r,RecoveryWindowInDays:7}),{operation:"secret:delete",command:`secret delete ${r}`,ok:!0,stdout:`Secret ${r} scheduled for deletion (recoverable for 7 days).`}}catch(n){return{operation:"secret:delete",ok:!1,error:tn(n?.message??String(n))}}}var fT=new Set(["http","queue","cli"]);async function Oy(e,t,r,n){if(!fT.has(r))return{operation:"function:config",ok:!1,error:`Unknown function mode '${r}'.`};let i=n.memory==null?void 0:Number(n.memory),o=n.timeout==null?void 0:Number(n.timeout);if(i!=null&&(!Number.isInteger(i)||i<128||i>10240))return{operation:"function:config",ok:!1,error:"Memory must be an integer between 128 and 10240 MB."};if(o!=null&&(!Number.isInteger(o)||o<1||o>900))return{operation:"function:config",ok:!1,error:"Timeout must be an integer between 1 and 900 seconds."};if(i==null&&o==null)return{operation:"function:config",ok:!1,error:"Provide a memory and/or timeout value."};try{let s=await j(e,t),c=new R(s.region),l=`${s.slug}-${t}-${r}`;await c.updateFunctionConfiguration({FunctionName:l,...i!=null?{MemorySize:i}:{},...o!=null?{Timeout:o}:{}});let a=[i!=null?`${i} MB`:"",o!=null?`${o}s`:""].filter(Boolean).join(", ");return{operation:"function:config",command:`update ${l} (${a})`,ok:!0,stdout:`Updated ${l}: ${a}.`}}catch(s){return{operation:"function:config",ok:!1,error:tn(s?.message??String(s))}}}var Hl=[{key:"http-errors",label:"HTTP function errors",namespace:"AWS/Lambda",metricName:"Errors",statistic:"Sum",comparison:"GreaterThanThreshold",fnMode:"http",unit:"errors / 5 min"},{key:"http-throttles",label:"HTTP function throttles",namespace:"AWS/Lambda",metricName:"Throttles",statistic:"Sum",comparison:"GreaterThanThreshold",fnMode:"http",unit:"throttles / 5 min"},{key:"http-duration",label:"HTTP function duration (avg)",namespace:"AWS/Lambda",metricName:"Duration",statistic:"Average",comparison:"GreaterThanThreshold",fnMode:"http",unit:"ms"},{key:"http-concurrency",label:"HTTP concurrent executions",namespace:"AWS/Lambda",metricName:"ConcurrentExecutions",statistic:"Maximum",comparison:"GreaterThanThreshold",fnMode:"http",unit:"concurrent"},{key:"queue-errors",label:"Queue function errors",namespace:"AWS/Lambda",metricName:"Errors",statistic:"Sum",comparison:"GreaterThanThreshold",fnMode:"queue",unit:"errors / 5 min"}];function hT(e){return Hl.find((t)=>t.key===e)}async function _y(e,t){try{let r=await j(e,t);return{ok:!0,alarms:await new X(r.region).describeAlarms({AlarmNamePrefix:`${r.slug}-${t}-`,MaxRecords:100}),presets:Hl}}catch(r){return{ok:!1,alarms:[],presets:Hl,error:tn(r?.message??String(r))}}}async function Ny(e,t,r,n){let i=hT(r);if(!i)return{operation:"alarm:create",ok:!1,error:`Unknown alarm metric '${r}'.`};if(!Number.isFinite(n)||n<0)return{operation:"alarm:create",ok:!1,error:"Provide a non-negative threshold."};try{let o=await j(e,t),s=new X(o.region),c=`${o.slug}-${t}-${i.key}`,l=i.fnMode?[{Name:"FunctionName",Value:`${o.slug}-${t}-${i.fnMode}`}]:[];return await s.putMetricAlarm({AlarmName:c,Namespace:i.namespace,MetricName:i.metricName,ComparisonOperator:i.comparison,Threshold:n,EvaluationPeriods:1,Period:300,Statistic:i.statistic,Dimensions:l,AlarmDescription:`ts-cloud: ${i.label} > ${n} ${i.unit}`}),{operation:"alarm:create",command:`alarm ${c}`,ok:!0,stdout:`Alarm ${c} armed at ${n} ${i.unit}.`}}catch(o){return{operation:"alarm:create",ok:!1,error:tn(o?.message??String(o))}}}async function $y(e,t,r){try{let n=await j(e,t);if(!r.startsWith(`${n.slug}-${t}-`))return{operation:"alarm:delete",ok:!1,error:"Refusing to delete an alarm outside this environment."};return await new X(n.region).deleteAlarms([r]),{operation:"alarm:delete",command:`delete alarm ${r}`,ok:!0,stdout:`Alarm ${r} deleted.`}}catch(n){return{operation:"alarm:delete",ok:!1,error:tn(n?.message??String(n))}}}function yT(e){let t=e.HasFault?"fault":e.HasError?"error":e.HasThrottle?"throttle":"ok";return{id:String(e.Id??""),timestamp:Number.isFinite(Number(e.StartTime))?new Date(Number(e.StartTime)*1000).toISOString():void 0,durationMs:Math.round((e.Duration??0)*1000),responseMs:Math.round((e.ResponseTime??0)*1000),status:t,method:e.Http?.HttpMethod??"-",url:e.Http?.HttpURL??"-",httpStatus:e.Http?.HttpStatus??0}}async function Sd(e,t,r=30){try{let n=await j(e,t),i=new Wl(n.region),o=new Date,s=new Date(o.getTime()-Math.min(360,Math.max(1,r))*60000),c=`${n.slug}-${t}-http`,l=await i.getTraceSummaries({startTime:s,endTime:o,filterExpression:`service("${c}")`});if(!l.summaries.length)l=await i.getTraceSummaries({startTime:s,endTime:o});return{ok:!0,traces:l.summaries.slice(0,100).map(yT)}}catch(n){return{ok:!1,traces:[],error:tn(n?.message??String(n))}}}async function Xl(e,t,r){try{let n=await j(e,t),i=`${n.slug}-${t}-scheduler`;if(r==="run"){let s=await _t(e,t,"schedule:run");return{operation:"scheduler:run",command:"schedule:run",ok:!0,stdout:tn(s||"Scheduler run triggered.")}}let o=new me(n.region);if(r==="enable")await o.enableRule({Name:i});else await o.disableRule({Name:i});return{operation:`scheduler:${r}`,command:`${r} ${i}`,ok:!0,stdout:`Scheduler rule ${i} ${r}d.`}}catch(n){return{operation:`scheduler:${r}`,ok:!1,error:tn(n?.message??String(n))}}}function dn(e){let t=vd(e.name),r=ep(e.configText);if(vT(e.configText,r.start,r.end,t))throw Error(`Site '${t}' already exists in cloud.config.ts`);let n=ST({...e,name:t}),i=e.configText.slice(0,r.end).trimEnd(),o=e.configText.slice(r.end),s=i.endsWith("{")?`
|
|
441
|
+
`:i.endsWith(",")?`
|
|
442
|
+
|
|
443
|
+
`:`,
|
|
444
|
+
|
|
445
|
+
`;return`${i}${s}${n}
|
|
446
|
+
${o}`}function My(e){let t=vd(e.name),r=ep(e.configText),n=Vy(e.configText,r.start,r.end,t);if(!n)throw Error(`Site '${t}' does not exist in cloud.config.ts`);let i=e.configText,o=n.nameStart;while(o>0&&i[o-1]!==`
|
|
447
|
+
`&&/\s/.test(i[o-1]))o--;let s=n.end+1;if(i[s]===",")s++;while(s<i.length&&i[s]!==`
|
|
448
|
+
`&&/\s/.test(i[s]))s++;if(i[s]===`
|
|
449
|
+
`)s++;return i.slice(0,o)+i.slice(s)}function Ly(e){let t=vd(e.siteName);if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(e.key))throw Error(`Invalid property key '${e.key}'`);let r=ep(e.configText),n=Vy(e.configText,r.start,r.end,t);if(!n)throw Error(`Site '${t}' does not exist in cloud.config.ts`);let i=e.configText,o=i.indexOf("{",n.nameStart),s=n.end,c=i.slice(o+1,s),l=new RegExp(`(^|[\\s,{])(${tp(e.key)})\\s*:`,"m").exec(c);if(l){let E=o+1+l.index+l[1].length,k=i.indexOf(":",E),O=bT(i,k+1,s);return`${i.slice(0,E)}${e.key}: ${e.valueText}${i.slice(O)}`}let a=i.slice(0,s).trimEnd(),m=a.endsWith("{")||a.endsWith(",")?"":",";return`${a}${m}
|
|
450
|
+
${e.key}: ${e.valueText},
|
|
451
|
+
${i.slice(s)}`}function By(e){if(e===!1)return"false";if(e===!0)return"true";return`{ provider: '${Lo(e.provider||"letsencrypt")}' }`}function jy(e){return`'${Lo(e)}'`}function Fy(e){let t=Object.entries(e).filter(([r])=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(r));if(t.length===0)return"{}";return`{
|
|
452
|
+
${t.map(([r,n])=>` ${r}: '${Lo(String(n))}',`).join(`
|
|
453
|
+
`)}
|
|
454
|
+
}`}function Zl(e){return/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(e.trim())}function Uy(e){let t=[...new Set(e.map((r)=>r.trim().toLowerCase()).filter(Boolean))];for(let r of t)if(!Zl(r))throw Error(`Alias '${r}' is not a valid hostname.`);if(t.length===0)return"[]";return`[${t.map((r)=>`'${Lo(r)}'`).join(", ")}]`}function zy(e){let t=Object.entries(e).map(([r,n])=>[r.trim(),String(n).trim()]).filter(([r,n])=>r&&n);if(t.length===0)return"{}";return`{
|
|
455
|
+
${t.map(([r,n])=>` '${Lo(r)}': '${Lo(n)}',`).join(`
|
|
456
|
+
`)}
|
|
457
|
+
}`}function bT(e,t,r){let n=t;while(n<r&&/\s/.test(e[n]))n++;let i=0,o,s=!1;for(;n<r;n++){let c=e[n];if(o){if(s){s=!1;continue}if(c==="\\"){s=!0;continue}if(c===o)o=void 0;continue}if(c==='"'||c==="'"||c==="`"){o=c;continue}if(c==="{"||c==="["||c==="("){i++;continue}if(c==="}"||c==="]"||c===")"){if(i===0)return n;i--;continue}if(c===","&&i===0)return n}return r}function Vy(e,t,r,n){let i=e.slice(t+1,r),o=new RegExp(`(^|[\\s,{])(${tp(n)})\\s*:\\s*\\{`,"m").exec(i);if(!o)return null;let s=t+1+o.index+o[1].length,c=e.indexOf("{",s);return{nameStart:s,end:qy(e,c)}}function ST(e){let r=[` ${vd(e.name)}: {`];if(Mo(r,"deploy",e.deploy),Mo(r,"root",e.root),Mo(r,"path",e.path),Mo(r,"domain",e.domain),Mo(r,"type",e.type),Mo(r,"build",e.build),Mo(r,"start",e.start),e.port!==void 0)r.push(` port: ${e.port},`);if(Mo(r,"pathRewriteStyle",e.pathRewriteStyle),e.ssl!==void 0)if(e.ssl===!1)r.push(" ssl: false,");else if(e.ssl===!0)r.push(" ssl: true,");else r.push(` ssl: { provider: '${Lo(e.ssl.provider||"letsencrypt")}' },`);if(e.env&&Object.keys(e.env).length>0){r.push(" env: {");for(let[n,i]of Object.entries(e.env)){if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(n))continue;r.push(` ${n}: '${Lo(String(i))}',`)}r.push(" },")}return r.push(" },"),r.join(`
|
|
458
|
+
`)}function Lo(e){return e.replace(/\\/g,"\\\\").replaceAll(String.fromCharCode(39),"\\'").replace(/\r/g,"\\r").replace(/\n/g,"\\n")}function vd(e){let t=e.trim();if(!/^[A-Za-z_$][\w$]*$/.test(t))throw Error(`Invalid site name '${e}'. Use a valid JavaScript object key, e.g. docs or marketingSite.`);return t}function Mo(e,t,r){if(r===void 0||r==="")return;let n=r.replace(/\\/g,"\\\\").replaceAll(String.fromCharCode(39),"\\'");e.push(` ${t}: '${n}',`)}function ep(e){let t=/\bsites\s*:\s*{/g.exec(e);if(!t)throw Error("Could not find a top-level sites: { ... } block in cloud.config.ts");let r=e.indexOf("{",t.index),n=qy(e,r);return{start:r,end:n}}function vT(e,t,r,n){let i=e.slice(t+1,r);return new RegExp(`(^|[\\s,{])${tp(n)}\\s*:`,"m").test(i)}function tp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function qy(e,t){let r=0,n,i=!1,o=!1,s=!1;for(let c=t;c<e.length;c++){let l=e[c],a=e[c+1];if(o){if(l===`
|
|
459
|
+
`)o=!1;continue}if(s){if(l==="*"&&a==="/")s=!1,c++;continue}if(n){if(i){i=!1;continue}if(l==="\\"){i=!0;continue}if(l===n)n=void 0;continue}if(l==="/"&&a==="/"){o=!0,c++;continue}if(l==="/"&&a==="*"){s=!0,c++;continue}if(l==='"'||l==="'"||l==="`"){n=l;continue}if(l==="{")r++;if(l==="}"){if(r--,r===0)return c}}throw Error("Could not find the closing brace for sites: { ... } in cloud.config.ts")}function Jy(e,t,r){let n=(Array.isArray(r)?r:String(r??"").split(",")).map(String).filter(Boolean);if(!n.length){if(t)return;let o=e.map((s)=>s.id);return o.length?o:["__no_authorized_telemetry_resources__"]}let i=n.map((o)=>e.find((s)=>s.id===o||s.slug===o)?.id).filter((o)=>!!o);if(i.length!==n.length)throw Error("One or more telemetry resources are outside your authorized scope.");return[...new Set(i)]}import{createHash as Gy}from"node:crypto";function Bo(e){let t=Number(e);return Number.isFinite(t)&&t>=0?t:null}function wT(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;let t=Date.parse(`${e}T12:00:00.000Z`);return Number.isFinite(t)?new Date(t).toISOString():null}function IT(e,t){if(!e||typeof e!=="object")return[];let r={source:t.name},n=[],i=t.now,o=(a,m,E,k=i)=>{if(m!==null)n.push({name:a,value:m,unit:E,timestamp:k,attributes:r})};o("storage.egress.month",Bo(e.monthBytes),"bytes"),o("storage.egress.today",Bo(e.todayBytes),"bytes"),o("storage.egress.projected_month",Bo(e.projectedMonthBytes),"bytes");let s=Bo(e.budgetBytes);if(s!==null&&s>0){o("storage.egress.budget",s,"bytes");let a=e.budgetUsedPercent,m=typeof a==="number"&&Number.isFinite(a)?a:Bo(e.monthBytes)!==null?Math.round(Bo(e.monthBytes)/s*1000)/10:null;o("storage.egress.budget_used_percent",m,"percent")}let c=t.maxReplayDays??45,l=Array.isArray(e.days)?e.days.slice(-c):[];for(let a of l){let m=wT(String(a?.date??"")),E=Bo(a?.bytes);if(!m||E===null)continue;n.push({name:"storage.egress.day",value:E,unit:"bytes",timestamp:m,attributes:r});let k=Bo(a?.downloads);if(k!==null)n.push({name:"storage.egress.day_downloads",value:k,unit:"count",timestamp:m,attributes:r})}return n}async function CT(e,t=process.env,r=fetch){let n=e.tokenEnv?t[e.tokenEnv]:void 0,i=await r(e.url,{headers:n?{Authorization:`Bearer ${n}`}:{},signal:AbortSignal.timeout(1e4)});if(!i.ok)throw Error(`HTTP ${i.status}`);return await i.json()}async function Wy(e,t){let r=[],n=[];if(!Array.isArray(e)||e.length===0)return{metrics:r,errors:n};let i=await Promise.all(e.map(async(o)=>{if(!o?.name||!o?.url)return{endpoint:o,error:"egress endpoint needs both a name and a url"};try{let s=await CT(o,t.env,t.fetchImpl);return{endpoint:o,report:s}}catch(s){return{endpoint:o,error:s instanceof Error?s.message:String(s)}}}));for(let o of i){let s=`egress:${o.endpoint?.name??"unnamed"}`;if("error"in o&&o.error){n.push({source:s,message:o.error});continue}r.push(...IT(o.report,{name:o.endpoint.name,now:t.now}))}return{metrics:r,errors:n}}class Ky{now;entries=new Map;constructor(e=Date.now){this.now=e}async getOrCreate(e,t,r,n){let i=this.entries.get(e);if(!r&&i&&i.expiresAt>this.now())return{value:await i.promise,cached:!0};let o=n().catch((s)=>{throw this.entries.delete(e),s});return this.entries.set(e,{expiresAt:this.now()+t,promise:o}),{value:await o,cached:!1}}invalidate(e){for(let t of this.entries.keys())if(t.startsWith(e))this.entries.delete(t)}}class Qy{now;lastRun=new Map;constructor(e=Date.now){this.now=e}shouldRun(e,t,r=!1){let n=this.now(),i=this.lastRun.get(e);if(!r&&i!=null&&n-i<t)return!1;return this.lastRun.set(e,n),!0}}var Yy=new Ky,ET=new Qy,TT=2000,AT=3600000;function kT(e,t){if(e.kind==="log"&&!t.collectLogs)return!1;if(e.kind==="trace"&&!t.collectTraces)return!1;if((e.kind==="request"||e.name.startsWith("request."))&&!t.collectRequestAnalytics)return!1;if(!["log","trace","request"].includes(e.kind)&&!e.name.startsWith("request."))return!0;let r=e.requestId??e.traceId??`${e.source}\x00${e.workloadId??""}\x00${e.timestamp}`;return Number.parseInt(Gy("sha256").update(r).digest("hex").slice(0,8),16)/4294967295<=t.samplingRate}function rn(...e){return`telemetry:${Gy("sha256").update(e.map((t)=>String(t??"")).join("\x00")).digest("hex").slice(0,40)}`}function Fa(e,t,r,n){if(!n)return;return e.listResources(t,r).find((i)=>i.slug===n)?.id}function RT(e,t){let r=String(t??"").toLowerCase();if(["debug","info","warn","warning","error","fatal"].includes(r))return r==="fatal"?"error":r;return/fatal|panic|exception|error/i.test(e)?"error":/warn|timeout|throttl|retr(?:y|ies)/i.test(e)?"warning":"info"}function Hy(e){let t=e.timestamp&&Number.isFinite(new Date(e.timestamp).getTime())?new Date(e.timestamp).toISOString():new Date().toISOString(),r={};try{let G=JSON.parse(e.message);if(G&&typeof G==="object"&&!Array.isArray(G))r=G}catch{}let n=Object.fromEntries(Object.entries(r).filter(([G])=>!/^(?:body|requestBody|responseBody|headers|authorization|cookie|cookies|query|queryString)$/i.test(G))),i=String(r.requestId??r.request_id??r["x-request-id"]??"")||void 0,o=String(r.traceId??r.trace_id??r["x-amzn-trace-id"]??"")||void 0,s=Number(r.durationMs??r.duration_ms??r.latencyMs??r.latency_ms),c=Number(r.statusCode??r.status_code??r.status),l=String(r.method??r.httpMethod??"")||void 0,a=Ai(String(r.pathTemplate??r.path??r.url??"")||void 0),m=String(r.releaseId??r.release_id??"")||void 0,E=String(r.deploymentId??r.deployment_id??"")||void 0,k={projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,source:e.source,timestamp:t,requestId:i,traceId:o,releaseId:m,deploymentId:E,workloadId:e.workloadId},O=Object.keys(r).length?JSON.stringify(n):e.message,q=[{...k,id:rn(e.source,e.name,t,O),kind:"log",name:e.name,level:RT(O,r.level),message:O,attributes:n}];if(l&&a&&Number.isFinite(c)){if(q.push({...k,id:rn("request",i,t,l,a,c),kind:"request",name:"http.request",method:l,pathTemplate:a,host:r.host,statusCode:c,durationMs:Number.isFinite(s)?s:void 0,bytesIn:Number(r.bytesIn)||void 0,bytesOut:Number(r.bytesOut)||void 0,region:r.region,cacheResult:r.cacheResult??r.cache,upstream:r.upstream,attributes:{userAgentFamily:r.userAgentFamily??"",protocol:r.protocol??""}}),Number.isFinite(s))q.push({...k,id:rn("request-duration",i,t),kind:"metric",name:"request.duration",value:s,unit:"ms",attributes:{method:l,pathTemplate:a,statusCode:c}});if(q.push({...k,id:rn("request-count",i,t),kind:"metric",name:"request.count",value:1,unit:"count",attributes:{method:l,pathTemplate:a,statusCode:c}}),c>=500)q.push({...k,id:rn("request-error",i,t),kind:"metric",name:"request.error",value:1,unit:"count",attributes:{method:l,pathTemplate:a,statusCode:c}})}return q}async function PT(e){let t=new Ve(e.controlPlane),r=je(e.controlPlane,e.projectId),n=new Date,i=[],o=[],s={projectId:e.projectId,environmentId:e.environmentId},c=V(e.config);try{let k=(c==="serverless"?await Xn(e.config,e.environment):await ti(e.config,e.environment,{includeSiteHealth:e.includeSiteHealth,telemetryOnly:e.lightweight}))??{};if(c==="serverless"){for(let q of k.functionsDetail??[]){let G=Fa(e.controlPlane,e.projectId,e.environmentId,q.key),Y={...s,resourceId:G,source:"cloudwatch",timestamp:n.toISOString(),workloadId:q.name,attributes:{provider:"aws",functionName:q.name,aggregationWindow:"24h"}};for(let[re,he,ee]of[["snapshot.traffic.requests_24h",q.invocations,"count"],["snapshot.errors.count_24h",q.errors,"count"],["snapshot.latency.p50_24h",q.p50,"ms"],["snapshot.latency.p95_24h",q.p95,"ms"],["snapshot.latency.p99_24h",q.p99,"ms"],["snapshot.saturation.throttles_24h",q.throttles,"count"],["snapshot.memory.max_24h",q.maxMem,"MB"]])if(Number.isFinite(Number(he)))i.push({...Y,id:rn("cloudwatch",q.name,re,n.toISOString()),kind:"metric",name:re,value:Number(he),unit:ee})}try{let q=await j(e.config,e.environment),G=new X(q.region),Y=new Date(n.getTime()-3600000),re=300;for(let he of q.functions){let ee=[{Name:"FunctionName",Value:he.name}],[Re,at,ze,Vt,ut]=await Promise.all([G.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:ee,StartTime:Y,EndTime:n,Period:300,Statistics:["Sum"]}),G.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Errors",Dimensions:ee,StartTime:Y,EndTime:n,Period:300,Statistics:["Sum"]}),G.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Duration",Dimensions:ee,StartTime:Y,EndTime:n,Period:300,ExtendedStatistics:["p50","p95","p99"]}),G.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Throttles",Dimensions:ee,StartTime:Y,EndTime:n,Period:300,Statistics:["Sum"]}),G.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"ConcurrentExecutions",Dimensions:ee,StartTime:Y,EndTime:n,Period:300,Statistics:["Maximum"]})]),Te=Fa(e.controlPlane,e.projectId,e.environmentId,he.mode),Qe=(Tt,ki,po,gi)=>{for(let Ri of Tt){let Pi=Ri.Timestamp&&Number.isFinite(new Date(Ri.Timestamp).getTime())?new Date(Ri.Timestamp).toISOString():void 0,xi=po(Ri);if(Pi&&xi!=null&&Number.isFinite(xi))i.push({...s,resourceId:Te,id:rn("cloudwatch-series",he.name,ki,Pi),kind:"metric",source:"cloudwatch",name:ki,timestamp:Pi,value:xi,unit:gi,workloadId:he.name,region:q.region,attributes:{provider:"aws",functionName:he.name,aggregationWindow:"300s"}})}};Qe(Re,"traffic.requests",(Tt)=>Tt.Sum,"count"),Qe(at,"errors.count",(Tt)=>Tt.Sum,"count"),Qe(ze,"latency.p50",(Tt)=>Tt.Percentiles?.p50,"ms"),Qe(ze,"latency.p95",(Tt)=>Tt.Percentiles?.p95,"ms"),Qe(ze,"latency.p99",(Tt)=>Tt.Percentiles?.p99,"ms"),Qe(Vt,"saturation.throttles",(Tt)=>Tt.Sum,"count"),Qe(ut,"saturation.concurrency",(Tt)=>Tt.Maximum,"count")}}catch(q){o.push({source:"cloudwatch:series",message:q instanceof Error?q.message:String(q)})}for(let q of(k.serverlessLogs??[]).slice(0,TT))i.push(...Hy({...s,source:`cloudwatch:${q.source}`,name:`${q.source}.log`,timestamp:q.timestamp,message:String(q.message),resourceId:Fa(e.controlPlane,e.projectId,e.environmentId,q.source)}));for(let q of k.queuesDetail??[]){let G={...s,source:"cloudwatch",timestamp:n.toISOString(),attributes:{queue:q.name}};i.push({...G,id:rn("queue-depth",q.name,n.toISOString()),kind:"metric",name:"queue.depth",value:Number(q.visible??q.depth??0),unit:"count"}),i.push({...G,id:rn("queue-inflight",q.name,n.toISOString()),kind:"metric",name:"queue.inflight",value:Number(q.inFlight??0),unit:"count"})}let O=await Sd(e.config,e.environment,30);if(!O.ok)o.push({source:"xray",message:O.error??"X-Ray traces are unavailable."});for(let q of O.traces)i.push({...s,id:rn("xray",q.id),kind:"trace",source:"xray",name:"http.trace",timestamp:q.timestamp??n.toISOString(),traceId:q.id,durationMs:q.durationMs,statusCode:q.httpStatus,method:q.method,pathTemplate:q.url,attributes:{status:q.status,responseMs:q.responseMs}})}else{let O=k.systemMetrics;if(k.metricsUnavailable||!O)o.push({source:"host",message:"The host metrics probe is unavailable."});else{let q=Number(O.memTotalMb)>0?Number(O.memUsedMb)/Number(O.memTotalMb)*100:0,G=Number(O.swapTotalMb)>0?Number(O.swapUsedMb)/Number(O.swapTotalMb)*100:0,Y=[["host.load",Number(O.load),"load"],["host.load.5m",Number(O.load5),"load"],["host.load.15m",Number(O.load15),"load"],["host.cpu.capacity",Number(O.cpus),"count"],["host.cpu.used_percent",Number(O.cpuUsedPct),"percent"],["host.memory.used",Number(O.memUsedMb)*1024*1024,"bytes"],["host.memory.total",Number(O.memTotalMb)*1024*1024,"bytes"],["host.memory.available",Number(O.memAvailableMb)*1024*1024,"bytes"],["host.memory.cache",Number(O.memCacheMb)*1024*1024,"bytes"],["host.memory.used_percent",q,"percent"],["host.swap.used",Number(O.swapUsedMb)*1024*1024,"bytes"],["host.swap.total",Number(O.swapTotalMb)*1024*1024,"bytes"],["host.swap.used_percent",G,"percent"],["host.disk.used_percent",Number(O.diskUsedPct),"percent"],["host.disk.used",Number(O.diskUsedGb)*1073741824,"bytes"],["host.disk.total",Number(O.diskTotalGb)*1073741824,"bytes"],["host.disk.inode_used_percent",Number(O.inodeUsedPct),"percent"],["host.network.rx",Number(O.networkRxBytes),"bytes"],["host.network.tx",Number(O.networkTxBytes),"bytes"],["host.network.rx_rate",Number(O.networkRxBytesPerSec),"bytes_per_second"],["host.network.tx_rate",Number(O.networkTxBytesPerSec),"bytes_per_second"],["host.network.rx_today",Number(O.networkRxBytesToday),"bytes"],["host.network.tx_today",Number(O.networkTxBytesToday),"bytes"],["host.network.rx_month",Number(O.networkRxBytesMonth),"bytes"],["host.network.tx_month",Number(O.networkTxBytesMonth),"bytes"],["host.processes",Number(O.processes),"count"],["host.uptime",Number(O.uptimeSeconds),"seconds"]];for(let[re,he,ee]of Y)if(Number.isFinite(he))i.push({...s,id:rn("host",re,n.toISOString()),kind:"metric",source:"host",name:re,timestamp:n.toISOString(),value:he,unit:ee});for(let re of k.siteHealth??[]){let he=String(re.project??e.config.project.slug),ee=String(re.name),Re=ee.startsWith(`${he}:`)?ee.slice(he.length+1):ee,at=`site:${he}:${Re}`,ze=Fa(e.controlPlane,e.projectId,e.environmentId,ee),Vt={...s,resourceId:ze,source:at,timestamp:re.checkedAt||n.toISOString(),host:re.route,attributes:{project:he,site:Re,route:String(re.route),status:String(re.status)}},ut=[["site.health.up",re.status==="live"?1:0,"boolean"],["site.http.status",Number(re.httpStatus),"status"],["site.response.time",Number(re.responseMs),"ms"]];if(re.tlsDaysRemaining!=null)ut.push(["site.tls.days_remaining",Number(re.tlsDaysRemaining),"days"]);for(let[Te,Qe,Tt]of ut)if(Number.isFinite(Qe))i.push({...Vt,id:rn(at,Te,Vt.timestamp),kind:"metric",name:Te,value:Qe,unit:Tt})}}}}catch(k){o.push({source:c==="serverless"?"aws":"host",message:k instanceof Error?k.message:String(k)})}{let k=e.config.infrastructure?.compute?.monitoring,O=typeof k==="object"?k?.egressEndpoints:void 0,q=await Wy(O,{now:n.toISOString()});o.push(...q.errors);for(let G of q.metrics)i.push({...s,id:rn(G.attributes.source,G.name,G.timestamp),kind:"metric",source:`egress:${G.attributes.source}`,name:G.name,timestamp:G.timestamp,value:G.value,unit:G.unit,attributes:G.attributes})}if(!e.lightweight)try{let k=await Si(e.config,e.environment),O=new ge(e.config,e.environment,{inventory:async()=>k});for(let q of k.workloads){let G=Fa(e.controlPlane,e.projectId,e.environmentId,q.links.service),Y={...s,resourceId:G,source:`runtime:${q.provider}`,timestamp:n.toISOString(),workloadId:q.id,releaseId:q.links.release,attributes:{status:q.status,provider:q.provider,service:q.links.service??""}};if(i.push({...Y,id:rn(q.id,"health",n.toISOString()),kind:"metric",name:"health.up",value:q.status==="running"?1:0,unit:"boolean"}),i.push({...Y,id:rn(q.id,"restarts",n.toISOString()),kind:"metric",name:"saturation.restarts",value:q.restartCount??0,unit:"count"}),q.resources?.memoryBytes!=null)i.push({...Y,id:rn(q.id,"memory",n.toISOString()),kind:"metric",name:"runtime.memory.used",value:q.resources.memoryBytes,unit:"bytes"});if(!q.capabilities.logs.supported)continue;try{let re=await O.logs(q.id,{limit:100,since:new Date(n.getTime()-300000)});for(let he of re.lines)i.push(...Hy({...s,resourceId:G,source:`runtime:${q.provider}`,name:`${q.links.service??q.name}.log`,timestamp:he.timestamp,message:he.message,workloadId:q.id}))}catch(re){o.push({source:`runtime:${q.provider}`,message:re instanceof Error?re.message:String(re)})}}for(let q of k.sources.filter((G)=>G.status!=="fresh"))o.push({source:q.id,message:q.message??`Runtime source is ${q.status}.`})}catch(k){o.push({source:"runtime",message:k instanceof Error?k.message:String(k)})}if(!e.lightweight)for(let k of e.controlPlane.listEvents({projectId:e.projectId,limit:1000})){let O=k.payload;i.push({...s,id:`telemetry:event:${k.id}`,resourceId:k.resourceId,kind:"event",source:"control-plane",name:k.type,timestamp:k.createdAt,level:k.level,message:k.type,deploymentId:k.operationId,releaseId:typeof O.releaseId==="string"?O.releaseId:void 0,traceId:k.correlationId,attributes:O})}let l=i.filter((k)=>kT(k,r)).map((k)=>({...k,sampled:r.samplingRate<1&&(k.kind==="log"||k.kind==="trace"||k.kind==="request"||k.name.startsWith("request."))})),a=t.appendMany(l).length;if(ET.shouldRun(e.projectId,AT,!e.lightweight))t.enforceRetention(r,e.projectId);let m=t.status(e.projectId,e.environmentId,r.rawDays,r.samplingRate);for(let k of o)if(!m.some((O)=>O.source===k.source))m.push({source:k.source,freshness:"unavailable",samplingRate:r.samplingRate,retentionDays:r.rawDays,estimatedDailyBytes:0,message:k.message});let E=n.toISOString();return e.controlPlane.setSetting(`telemetry.collection:${e.projectId}:${e.environmentId??"all"}`,{generatedAt:E,errors:o,statuses:m,policy:r}),{collected:a,cached:!1,generatedAt:E,statuses:m,errors:o,policy:r}}async function Un(e){let r=`${`${e.projectId}:${e.environmentId??"all"}:${e.environment}`}:${e.lightweight?"lightweight":"full"}`,n=V(e.config)==="serverless"?300000:60000,i=await Yy.getOrCreate(r,n,!!e.force,()=>PT(e));return{...i.value,cached:i.cached}}function Xy(e){Yy.invalidate(`${e}:`)}function Zy(e,t={}){let r=t.shell||(process.platform==="win32"?"powershell.exe":"bash"),n=Bun.spawn([r,"-i"],{stdin:"pipe",stdout:"pipe",stderr:"pipe",cwd:t.cwd,env:{...process.env,TERM:"xterm-256color",PS1:"\\w $ "}}),i=new TextDecoder,o=async(s)=>{if(!s)return;let c=s.getReader();try{for(;;){let{done:l,value:a}=await c.read();if(l)break;if(a)e(i.decode(a))}}catch{}};if(o(n.stdout),o(n.stderr),t.onExit)n.exited.then((s)=>t.onExit(s)).catch(()=>{});return{write(s){try{n.stdin.write(s),n.stdin.flush()}catch{}},close(){try{n.stdin.end()}catch{}try{n.kill()}catch{}}}}var LT="127.0.0.1",BT=7676,tb=65536,pb="ts-cloud-dashboard-",aa=DT(MT(import.meta.url));function jT(e){try{return process.kill(e,0),!0}catch(t){return t?.code!=="ESRCH"}}function FT(e=Cd(),t=jT){let r=0;for(let n of eb(e,{withFileTypes:!0})){if(!n.isDirectory()||!n.name.startsWith(pb))continue;let i=Et(e,n.name),o=n.name.match(/^ts-cloud-dashboard-(\d+)-/);if(o){let s=Number(o[1]);if(s===process.pid||t(s))continue}else if(eb(i).length>0)continue;Ss(i,{recursive:!0,force:!0}),r+=1}return r}var UT={".html":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".ico":"image/x-icon"};function S(e,t=200,r={}){return new Response(JSON.stringify(e,null,2),{status:t,headers:{"content-type":"application/json; charset=utf-8",...r}})}function zT(e,t,r,n){let i=new TextEncoder,o=Math.max(0,Math.floor(r)),s,c,l=!1,a=new ReadableStream({start(m){let E=()=>{if(l)return;if(l=!0,s?.(),c)clearInterval(c);n.removeEventListener("abort",E);try{m.close()}catch{}},k=(q)=>{if(l)return;if(q.reset)m.enqueue(i.encode(`event: reset
|
|
460
|
+
data: ${JSON.stringify({cursor:q.cursor,droppedBytes:q.droppedBytes})}
|
|
461
|
+
|
|
462
|
+
`));for(let G of q.chunks.filter((Y)=>Y.cursor>o))o=G.cursor,m.enqueue(i.encode(`id: ${G.cursor}
|
|
463
|
+
event: ${G.stream}
|
|
464
|
+
data: ${JSON.stringify(G)}
|
|
465
|
+
|
|
466
|
+
`));if(q.state!=="open")m.enqueue(i.encode(`event: state
|
|
467
|
+
data: ${JSON.stringify({state:q.state,error:q.error,cursor:q.cursor})}
|
|
468
|
+
|
|
469
|
+
`)),E()};s=e.subscribe(t.id,t.workloadId,(q)=>k(e.read(q.id,q.workloadId,o)??q));let O=e.read(t.id,t.workloadId,o);if(!O)return E();if(k(O),l)return;c=setInterval(()=>{if(!l)m.enqueue(i.encode(`event: heartbeat
|
|
470
|
+
data: ${JSON.stringify({cursor:o,at:new Date().toISOString()})}
|
|
471
|
+
|
|
472
|
+
`))},15000),c.unref?.(),n.addEventListener("abort",E,{once:!0})},cancel(){if(l=!0,s?.(),c)clearInterval(c)}});return new Response(a,{headers:{"cache-control":"no-cache, no-transform",connection:"keep-alive","content-type":"text/event-stream; charset=utf-8","x-accel-buffering":"no"}})}var VT=new Set(["action","operation","site","name","username","database","secretId","port","key","resourceId","environmentId"]);function qT(e,t,r,n,i){let o={};if(r&&typeof r==="object"&&!Array.isArray(r))for(let[c,l]of Object.entries(r)){if(!VT.has(c)||!["string","number","boolean"].includes(typeof l))continue;o[c]=typeof l==="string"?l.slice(0,256):l}let s=String(o.resourceId||o.site||o.secretId||o.database||o.name||t);return{method:e.toUpperCase(),path:t,target:s,status:n,outcome:n<400?"succeeded":"failed",durationMs:Math.max(0,Math.round(i)),input:o}}var JT=No("ts-cloud-dummy-password");function Ed(e,t=200){return new Response(e,{status:t,headers:{"content-type":"text/plain; charset=utf-8"}})}function WT(e,t,r=process.env){let n=r.TS_CLOUD_DASHBOARD_ORIGIN?.trim()||(r.TS_CLOUD_UI_DOMAIN?.trim()?`https://${r.TS_CLOUD_UI_DOMAIN.trim().replace(/^https?:\/\//,"")}`:""),i=["0.0.0.0","::"].includes(e)?void 0:e,o=n||(i&&["127.0.0.1","localhost","::1"].includes(i)?`http://${i.includes(":")?`[${i}]`:i}:${t}`:"");if(!o)return;try{let s=new URL(o),c=["127.0.0.1","localhost","::1"].includes(s.hostname);if(s.protocol!=="https:"&&!(s.protocol==="http:"&&c)||s.username||s.password||s.search||s.hash||s.pathname!=="/"&&s.pathname!=="")return;return s.origin}catch{return}}function HT(e,t){if(t&&Object.hasOwn(e.environments??{},t))return t;return Object.keys(e.environments??{})[0]??"production"}function GT(e,t,r){return r&&e.includes(r)?r:t}function rb(e,t,r){return e==null||t-e>=r}async function KT(e){let t=[Et(aa,"..","..","..","..",".env"),Et(e,".env"),Et(e,".env.local"),Et(e,".env.production")];for(let r of t){if(!lo(r))continue;let n=await Fi(r,"utf8").catch(()=>"");for(let i of n.split(`
|
|
473
|
+
`)){let o=i.trim();if(!o||o.startsWith("#")||!o.includes("="))continue;let s=o.indexOf("="),c=o.slice(0,s).trim(),l=o.slice(s+1).trim();if(!/^[A-Z_][A-Z0-9_]*$/i.test(c)||process.env[c]!=null)continue;if(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))l=l.slice(1,-1);process.env[c]=l}}}function QT(e){return[Et(e,"config","cloud.ts"),Et(e,"config","cloud.js"),Et(e,"cloud.config.ts"),Et(e,"cloud.config.js")].find((r)=>lo(r))??null}function ca(e){return e.infrastructure?.compute?.sshKeys??[]}function nb(e,t){let r=e.infrastructure??(e.infrastructure={}),n=r.compute??(r.compute={});n.sshKeys=t}function YT(e,t,r){let n=e.sites??(e.sites={});n[t]=r}function rp(e){return hs(e.infrastructure?.compute?.firewall?.allowedPorts??[])}function ib(e,t){let r=e.infrastructure??(e.infrastructure={}),n=r.compute??(r.compute={}),i=n.firewall??(n.firewall={});i.allowedPorts=t}async function oe(e){return await e.json().catch(()=>({}))}function sa(e,t){let r=String(e.scopeType??"environment");if(!["project","environment","service","function","preview"].includes(r))throw Error("Configuration scopeType must be project, environment, service, function, or preview.");let n=String(e.scopeId??(r==="project"?t.projectId:r==="environment"?t.environmentId??"":""));if(!n)throw Error("Configuration scopeId is required.");if(r==="project")return{type:r,id:n};if(r==="environment")return{type:r,id:n,environmentId:n};if(r==="service"||r==="function")return{type:r,id:n,environmentId:String(e.environmentId??t.environmentId??"")||void 0,resourceId:n};return{type:r,id:n,environmentId:String(e.environmentId??t.environmentId??"")||void 0,resourceId:String(e.resourceId??"")||void 0,previewId:n}}function XT(e){if(["GET","HEAD","OPTIONS"].includes(e.method.toUpperCase()))return!0;let t=e.headers.get("sec-fetch-site");if(t==="cross-site")return!1;let r=e.headers.get("origin");if(!r)return!0;let n=new URL(e.url);if(r===n.origin)return!0;if(t!=="same-origin")return!1;try{let i=new URL(r),o=(e.headers.get("x-forwarded-host")??e.headers.get("host")??n.host).split(",")[0].trim(),s=e.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();if(!/^[A-Za-z0-9.-]+(?::\d{1,5})?$/.test(o)||i.host!==o)return!1;return!s||i.protocol===`${s}:`}catch{return!1}}var ZT=new Set(["owner","admin","deployer","operator","viewer","auditor"]),eA=new Set(["organization","project","environment","resource"]),tA=new Set(["POST /api/organization/invitations","DELETE /api/organization/invitations","POST /api/organization/invitations/resend","PATCH /api/organization/memberships","DELETE /api/organization/memberships","POST /api/organization/grants","DELETE /api/organization/grants","POST /api/auth/oidc/providers","PATCH /api/auth/oidc/providers","POST /api/automation/service-accounts","PATCH /api/automation/service-accounts","POST /api/automation/tokens","POST /api/automation/tokens/rotate","DELETE /api/automation/tokens","POST /api/security/policies","PATCH /api/security/policies","POST /api/security/waivers","DELETE /api/security/waivers","POST /api/sources/connections","PATCH /api/sources/connections","DELETE /api/sources/connections","POST /api/sources/deploy-keys","DELETE /api/sources/deploy-keys","PATCH /api/telemetry/settings","POST /api/health/checks","PATCH /api/health/checks","POST /api/alerts/rules","PATCH /api/alerts/rules","POST /api/alerts/silences","POST /api/spend/budgets","PATCH /api/spend/budgets","DELETE /api/spend/budgets","POST /api/spend/check","POST /api/spend/release","POST /api/spend/anomalies/acknowledge","POST /api/protection/attack-mode","POST /api/protection/pause","POST /api/protection/ip-rules","DELETE /api/protection/ip-rules","POST /api/notifications/channels","PATCH /api/notifications/channels","POST /api/notifications/routes","PATCH /api/notifications/routes","POST /api/jobs","PATCH /api/jobs","POST /api/jobs/reconcile","POST /api/workers/action","POST /api/data-services","POST /api/data-services/action","POST /api/data-services/dependencies","POST /api/data-services/management","POST /api/data-services/reveal","POST /api/backups/destinations","POST /api/backups/destinations/test","POST /api/backups/policies","POST /api/backups/run","POST /api/backups/verify","POST /api/backups/restore","POST /api/backups/recovery-points","POST /api/backups/retention","POST /api/configuration/reveal","POST /api/configuration/transfer","POST /api/configuration/bulk","DELETE /api/configuration","POST /api/volumes","POST /api/volumes/attach","POST /api/volumes/detach","POST /api/volumes/resize","POST /api/volumes/snapshot","POST /api/volumes/restore","POST /api/volumes/adopt","POST /api/volumes/discover","DELETE /api/volumes","POST /api/fleet","POST /api/fleet/action","POST /api/capacity","POST /api/capacity/member","POST /api/capacity/action","POST /api/capacity/explain","POST /api/regions","POST /api/regions/action","POST /api/maintenance/cleanup-preview","POST /api/maintenance/cleanup-apply","POST /api/maintenance/drill","POST /api/maintenance/drill-run","POST /api/sources/webhooks","PATCH /api/sources/webhooks","DELETE /api/sources/webhooks","POST /api/onboarding/registries","PATCH /api/onboarding/registries","DELETE /api/onboarding/registries","POST /api/runtime/exec-sessions","POST /api/runtime/files/read","POST /api/runtime/files/write","POST /api/onboarding/apply","PATCH /api/queue/settings","DELETE /api/queue/history","POST /api/serverless/secrets","DELETE /api/serverless/secrets"]);function wd(e){let t=String(e??"");return ZT.has(t)?t:void 0}function Ua(e){let t=String(e.scopeType??"organization");if(!eA.has(t))return;if(t==="organization")return{type:"organization"};let r=String(e.scopeId??"").trim();return r?{type:t,id:r}:void 0}async function bs(e,t,r={}){let n=V(e),i={mode:n,environment:t,environments:Object.keys(e.environments??{}),project:{name:e.project.name,slug:e.project.slug,region:e.project.region}};try{return{...(n==="serverless"?await Xn(e,t):await ti(e,t,{includeSiteHealth:r.includeSiteHealth}))??{},...i}}catch{return{...i}}}function rA(e,t){if(!e)return t;let r={...t,...Array.isArray(e.sites)?{sites:e.sites}:{},...Array.isArray(e.sitesDetail)?{sitesDetail:e.sitesDetail}:{},...Array.isArray(e.siteHealth)?{siteHealth:e.siteHealth}:{}};if(r.mode!=="serverless"&&Array.isArray(r.sites))r.topology=Xr(r,{project:r.project?.name,environment:r.environment});return r}function nA(e){let t=[Et(e,"packages","ui"),Et(aa,"..","..","..","ui"),Et(aa,"..","..","ui"),Et(aa,"..","ui-src"),Et(aa,"..","..","ui-src"),Et(aa,"..","..","dist","ui-src")];for(let r of t)if(lo(Et(r,"pages"))&&lo(Et(r,"package.json")))return r;return null}async function iA(e,t){let r=nA(e);if(!r)return null;let n;try{n=ip(Et(Cd(),`${pb}${process.pid}-`));let i=Et(r,"node_modules",".bin","stx"),o=lo(i)?[i,"build","--pages","pages","--out",n,"--no-sitemap","--no-cache"]:["bunx","--bun","@stacksjs/stx","build","--pages","pages","--out",n,"--no-sitemap","--no-cache"],s=Bun.spawn(o,{cwd:r,stdout:"pipe",stderr:"pipe",env:{...process.env,TSCLOUD_DASHBOARD_DATA:_o(t)}}),[c,l,a]=await Promise.all([new Response(s.stdout).text(),new Response(s.stderr).text(),s.exited]);if(a!==0){if(Ss(n,{recursive:!0,force:!0}),process.env.TSCLOUD_DASHBOARD_VERBOSE)console.warn(`ts-cloud dashboard: live UI build failed; serving the pre-built UI.
|
|
474
|
+
${c}
|
|
475
|
+
${l}`);return null}return n}catch(i){if(n)Ss(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 oA(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:$t(ca(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 gb(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 sA(e,t){return gb(t).find((r)=>r.id===e)}function ob(e){if(e.length<=tb)return e;return`${e.slice(0,tb)}
|
|
476
|
+
|
|
477
|
+
[output truncated]`}async function sb(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 np(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([sb(r.stdout,"stdout",t.onOutput),sb(r.stderr,"stderr",t.onOutput),r.exited]);return{action:e.id,command:["cloud",...e.command].join(" "),exitCode:s,ok:s===0,stdout:ob(i),stderr:ob(o)}}finally{t.signal?.removeEventListener("abort",n)}}function aA(){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 cA=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 dA(e){let t=za(e);if(t&&t!==".html")return!1;let r=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(r==="/")return!1;return!cA.has(r)}var uA={"/":"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 ab(e,t){if(t.role==="admin")return!0;let r=za(e);if(r&&r!==".html")return!0;if(t.organizationSource==="legacy")return!dA(e);let n=e.replace(/\.html$/,"").replace(/\/+$/,"")||"/";if(n==="/access-denied")return!0;let i=uA[n];return!!i&&!!t.capabilities?.includes(i)}function lA(e,t){let r=decodeURIComponent(t).replace(/^\/+/,""),i=OT(r===""?"index.html":r);if(i.startsWith("..")||i.includes("/../"))return null;let o=Et(e,i);if(lo(o)&&!lb(o).isDirectory())return o;if(!za(o)&&lo(`${o}.html`))return`${o}.html`;if(!za(o)&&lo(Et(o,"index.html")))return Et(o,"index.html");return null}async function cb(e,t){let r=lA(e,t);if(!r){let o=Et(e,"404.html");if(lo(o))return new Response(await Fi(o),{status:404,headers:{"content-type":"text/html; charset=utf-8"}});return Ed("Not found",404)}if(lb(r).isDirectory())return Ed("Not found",404);let n=await Fi(r),i=UT[za(r)]??"application/octet-stream";return new Response(n,{headers:{"content-type":i}})}var Id=["observe","backup","restore","restart","resize","version","rotate","expose","delete","logs","slow_queries","users","databases"],db=new WeakMap;async function ub(e){let t=db.get(e);if(t)return t;let r=await import("./chunk-jh1593zx.js"),n=new r.SpendStore(e),i={store:n,service:new r.SpendService(n),gate:new r.SpendGate(e)};return db.set(e,i),i}async function Zt(e={}){FT();let t=e.cwd??process.cwd(),r=e.host??LT,n=e.port??BT,i=e.cliEntry??process.argv[1];if(e.box)process.env.TS_CLOUD_DASHBOARD_BOX="1";await KT(t);let o=e.config??await Ei(),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 m=Object.keys(o.environments??{}),E=HT(o,e.environment),k=QT(t),O=await bs(o,E),q=new Map([[E,O]]),G=new Map([[E,Date.now()]]),Y=new Map([[E,Date.now()]]),re=new Map,he=Math.min(300000,Math.max(5000,Number(process.env.TS_CLOUD_DASHBOARD_REFRESH_MS)||30000)),ee=Math.min(1800000,Math.max(60000,Number(process.env.TS_CLOUD_DASHBOARD_SITE_REFRESH_MS)||300000)),Re=V(o)!=="serverless",at=(I)=>{let Ce=q.get(I);if(Ce&&!rb(G.get(I),Date.now(),he))return Promise.resolve(Ce);let Ne=re.get(I);if(Ne)return Ne;let we=!Re||rb(Y.get(I),Date.now(),ee),We=bs(o,I,{includeSiteHealth:we}).then((mt)=>{let N=q.get(I),Hr=we?mt:rA(N,mt);if(q.set(I,Hr),G.set(I,Date.now()),we)Y.set(I,Date.now());if(N?._serverReachable!==Hr._serverReachable||N?._metricsStatus!==Hr._metricsStatus||(N?.sitesDetail?.length??0)!==(Hr.sitesDetail?.length??0))gi();return Hr}).finally(()=>re.delete(I));return re.set(I,We),We},ze=no(t),Vt=process.env.TS_CLOUD_DASHBOARD_TELEMETRY?.trim();if(e.box&&Vt!=="0"&&(Vt==="1"||!o.cloud?.attachTo)){let I=!1,Ce=Date.now()+300000,Ne=async()=>{if(I)return;I=!0;try{let We=Date.now(),mt=We>=Ce;if(mt)Ce=We+300000;let N=a.environments.get(E);await Un({controlPlane:a.store,projectId:a.project.id,environmentId:N?.id,config:o,environment:E,force:!0,lightweight:!0,includeSiteHealth:mt})}catch(We){if(e.verbose)console.warn(` ts-cloud dashboard: background telemetry collection failed: ${We instanceof Error?We.message:String(We)}`)}finally{I=!1}};Ne(),setInterval(()=>void Ne(),60000).unref?.()}let Te=new Map,Qe=new Map,Tt=new Set,ki=0;function po(I,Ce){if(I.role==="admin"&&!a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`))return I;let Ne=a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`),we=Ne?a.store.getMembershipForActor(a.organization.id,Ne.id):void 0;if(!we||we.status!=="active")return{...I,role:"member",sites:{},capabilities:[]};let We=a.store.listGrants(we.id),mt=a.store.resolveAuthorizationTarget(a.organization.id,we.scope)??a.store.resolveAuthorizationTarget(a.organization.id,{type:"project",id:a.project.id}),N=Zr({membership:we,grants:We,target:mt});if(we.roleTemplate==="owner"||we.roleTemplate==="admin")return{...I,role:"admin",sites:{},organizationRole:we.roleTemplate,organizationSource:we.source,capabilities:N};let Hr=a.environments.get(Ce),or={};for(let Xe of a.store.listResources(a.project.id,Hr?.id).filter((dt)=>dt.kind==="application")){let dt=a.store.resolveAuthorizationTarget(a.organization.id,{type:"resource",id:Xe.id});if(!dt||!Z({membership:we,grants:We,capability:"project:read",target:dt}).allowed)continue;or[Xe.slug]=Z({membership:we,grants:We,capability:"config:write",target:dt}).allowed?"owner":"collaborator"}return{...I,role:"member",sites:or,organizationRole:we.roleTemplate,organizationSource:we.source,capabilities:N}}function gi(){ki+=1,Te.clear();for(let I of Tt)Ss(I,{recursive:!0,force:!0});Tt.clear()}let Ri=(I,Ce)=>`${Ce}:${I.role==="admin"?"admin":`member:${Object.entries(I.sites).sort(([Ne],[we])=>Ne.localeCompare(we)).map(([Ne,we])=>`${Ne}=${we}`).join(",")}`}:${[...I.capabilities??[]].sort().join(",")}`;async function Pi(I,Ce){let Ne=po(I,Ce),we=Ri(Ne,Ce),We=Te.get(we);if(We)return We;let mt=Qe.get(we);if(mt)return mt;let N=ki,Hr=(async()=>{let or=q.get(Ce)??await bs(o,Ce);q.set(Ce,or);let Xe={...ql(or,{user:Ne,slug:o.project.slug}),viewer:{role:Ne.role,organizationRole:Ne.organizationRole,organizationSource:Ne.organizationSource,capabilities:Ne.capabilities??[]}},dt=await iA(t,Xe);if(dt&&N!==ki)return Ss(dt,{recursive:!0,force:!0}),ze?.uiRoot;if(dt)Tt.add(dt);let Br=dt??ze?.uiRoot;if(Br)Te.set(we,Br);return Br})();Qe.set(we,Hr);try{return await Hr}finally{Qe.delete(we)}}let xi=await Pi({username:"",passwordHash:"",role:"admin",sites:{}},E);if(!xi)throw Error("ts-cloud dashboard UI not found. Run `bun run build` in ts-cloud or reinstall the package.");let J=new WeakMap,pe=process.env.TS_CLOUD_DASHBOARD_TERMINAL!=="0",Ie=process.env.TS_CLOUD_DASHBOARD_AUTH==="0";if(Ie&&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 ke=!Ie,Dt=Kh(t),rr=ke?Zh(t,process.env.TS_CLOUD_UI_USERNAME?.trim()||"admin"):void 0,ve=new De(a.store,{encryptionKey:D(t)}),pt=new Ue(a.store),ct=new Rt(a.store),Je=new Gt(a.store,{encryptionKey:D(t)}),Jr=new Nn(a.store),vs=new Dn(a.store,{cwd:t}),Di=new kn(a.store,{encryptionKey:D(t)}),kt=new b(a.store,{workerId:`dashboard:${process.pid}`}),Ot=new Ht(a.store),Ui=new Wt(a.store,D(t)),go=new hr(a.store),Va=new Rr(Ot,kt,Ui),mo=o.project?.region??"us-east-1",op=D(t),Wn=new vr(go,{encryptionKey:op,backends:[new St(a.store,op),new yr(new H(mo),mo),new Sr(new qe(mo),mo),new br]});await Qr(Wn,a,o);let Td=new le(mo),mb={aws_rds:new vn(new An(Td)),aws_aurora:new Tn(new In(Td)),aws_elasticache:new En(new Rn(new te(mo))),server:new wn(new Ze),container:new Cn(new Ze)},sp=(I)=>mb[I.provider],sr=new Ln(a.store),jo=new Or(sr,kt),ap=new Mn(Ui),fb={managed_database:new gu(Ot,Td),logical_database:new bu(Ot,Ui),volume:new vu,files:new yu(t),control_plane:new Iu(a.store,t),infrastructure:new Eu(new va(mo))},hb=(I)=>fb[I.resourceKind],yb=(I)=>I.provider==="aws_backup"?void 0:ap,Ad=new nt(a.store),kd=[new Nt,new Mr(A(t,"volumes"))],Vi=new Lr(Ad,kd,kt),ua=new Ae(a.store),Oi=new un(ua,[new Ye("aws"),new Ye("hetzner"),new Ye("ssh")],kt),fo=new pn(a.store),cp=new mn(fo,ua),Fo=new gn(a.store),dp=new fn(Fo,kt),qi=new hn(a.store),Rd=new yn(qi,kt),up=["releases","artifacts","operations","logs","previews","snapshots","orphaned_resources"].map((I)=>new Sn(I,a.store,a.project.id,a.organization.id)),Er=new _r(a.store),lp=new On(Er,{queue:kt}),nr=new Fe(a.store),ho=new Be(a.store),ii=new et(a.store),Ge=new ot(a.store,{encryptionKey:D(t)}),bb=()=>ub(a.store);for(let I of a.environments.values())$r(Er,o,{organization:a.organization,project:a.project,environment:I,resources:a.store.listResources(a.project.id,I.id)});let oi=new tr(Ge,{emailImpl:async(I)=>{let{email:Ce}=await import("./chunk-yn34zgr2.js");return Ce.send(I)}}),pp=async(I)=>{let Ce=Ur(Ge,a.project.id,I),Ne=[];for(let we of Ce.filter((We)=>We.notify&&We.alert))Ne.push(...await oi.deliverAll(oi.enqueue(a.organization.id,we.alert,we.transition)));return Ne.push(...await oi.deliverAll(oi.enqueueRemindersAndEscalations(a.organization.id,Ge.listAlerts(a.project.id,{environmentId:I,states:["firing"]})))),Ne.push(...await oi.retryDue()),{evaluations:Ce,deliveries:Ne}},Pd=!1,Sb=async()=>{if(Pd)return;Pd=!0;try{for(let I of a.environments.values())for(let Ce of Ge.listHealthChecks(a.project.id,I.id).filter((Ne)=>Ne.enabled)){let Ne=Ge.listHealthResults(Ce.id,1)[0];if(Ne&&Date.now()-new Date(Ne.checkedAt).getTime()<Ce.intervalSeconds*1000)continue;let we=await new Oe(Ge).runAndEvaluate(Ce);for(let We of we.evaluations.filter((mt)=>mt.notify&&mt.alert))await oi.deliverAll(oi.enqueue(a.organization.id,We.alert,We.transition))}}finally{Pd=!1}},gp=setInterval(()=>{for(let I of a.environments.values())pp(I.id).catch((Ce)=>console.error("ts-cloud alert evaluation failed:",Ce))},60000);gp.unref?.();let mp=setInterval(()=>{Sb().catch((I)=>console.error("ts-cloud health check evaluation failed:",I))},30000);mp.unref?.();let fp=setInterval(()=>{try{lp.tick()}catch(I){console.error("ts-cloud scheduled job evaluation failed:",I)}},30000);fp.unref?.();let hp=setInterval(()=>{try{jo.enqueueDue(),jo.enqueueRetention()}catch(I){console.error("ts-cloud backup policy evaluation failed:",I)}},30000);hp.unref?.(),nr.cleanup();let yp=setInterval(()=>{try{nr.cleanup()}catch(I){console.error("ts-cloud preview cleanup failed:",I)}},3600000);yp.unref?.();let vb=e.queueWorker??!0,wb=aA(),Ib=async(I,Ce)=>{let we=(I.environmentId?a.store.listEnvironments(I.projectId).find((We)=>We.id===I.environmentId):void 0)?.slug??String(E);if(Ce.kind==="dashboard_operation"&&Ce.operationId){let We=q.get(we)??O,mt=xn(Ce.operationId,o,We);if(!mt||mt.danger||!["scheduler","backup","worker"].includes(mt.group))return{ok:!1,stderr:"The allowlisted dashboard operation is no longer available."};let N=await Dr(o,we,mt);return{ok:N.ok,stdout:N.stdout,stderr:N.stderr??N.error,retryable:/temporar|unavailable|timeout|network/i.test(N.stderr??N.error??""),output:{command:N.command??null,operation:N.operation}}}if(Ce.kind==="serverless_scheduler"){let We=await Xl(o,we,"run");return{ok:We.ok,stdout:We.stdout,stderr:We.error,retryable:/temporar|unavailable|timeout|network/i.test(We.error??""),output:{command:We.command??null,operation:"serverless_scheduler"}}}return{ok:!1,stderr:`No safe executor is configured for ${Ce.kind}.`}},qa=vb?new $o(kt,{...da({store:a.store,execute:async(I,Ce)=>{let Ne=Ce.operation.input&&typeof Ce.operation.input==="object"&&!Array.isArray(Ce.operation.input)?Ce.operation.input:{},we=Ne.source&&typeof Ne.source==="object"?Ne.source:void 0,We=t,mt,N,Hr;try{if(we?.bindingId&&we?.connectionId&&we?.commitSha){let Xe=Je.getBinding(String(we.bindingId)),dt=Je.getConnection(String(we.connectionId));if(!Xe||!dt||Xe.connectionId!==dt.id)throw Error("Queued source binding is no longer available");let wr=(Xe.repositoryId?Je.getRepository(Xe.repositoryId):Je.listRepositories(dt.id).find((Es)=>Es.fullName.toLowerCase()===Xe.repositoryFullName.toLowerCase()))?.cloneUrl;if(!wr&&dt.provider==="generic_ssh")wr=`git@${new URL(dt.host).hostname}:${Xe.repositoryFullName}.git`;if(!wr)wr=new URL(`/${Xe.repositoryFullName}.git`,dt.host.endsWith("/")?dt.host:`${dt.host}/`).href;let ye=Xe.deployKeyId?Je.getDeployKey(Xe.deployKeyId):void 0,Mt=ye&&Xe.deployKeyId?{...ye,privateKey:Je.getDeployPrivateKey(Xe.deployKeyId)}:void 0;if(["github","gitlab","bitbucket","gitea"].includes(dt.provider)&&I.target.previewId){let Es=wo(dt,Je.getCredential(dt.id)),de=nr.previews.getInstance(I.target.previewId);Hr=async(si,Ka)=>{try{await Es.setCommitStatus(Xe.repositoryFullName,String(we.commitSha),{state:si,url:de?.url,description:Ka})}catch(Ts){Ce.log(`Could not publish source status: ${Ts instanceof Error?Ts.message:String(Ts)}`,{stream:"stderr"})}},await Hr("pending",`Preview deployment started for ${String(we.commitSha).slice(0,12)}`)}mt=ip(Et(Cd(),"ts-cloud-queued-source-")),Ce.log(`Checking out immutable source commit ${we.commitSha}.`,{stream:"system"}),We=(await Wd({remote:wr,binding:Xe,destination:Et(mt,"checkout"),ref:String(we.branch??Xe.defaultBranch),commitSha:String(we.commitSha)},{credential:Je.getCredential(dt.id),deployKey:Mt})).directory}if(Ce.operation.kind!=="preview.destroy"){let Xe=I.target.previewId?nr.previews.getInstance(I.target.previewId):void 0,dt=Xe?nr.previews.getDefinition(Xe.definitionId):void 0,Br=Ce.operation.resourceId?a.store.getResource(Ce.operation.resourceId):void 0;if(N=await Wn.resolve({projectId:a.project.id,environmentId:Ce.operation.environmentId,resourceId:Ce.operation.resourceId,functionId:Br?.kind==="function"?Br.id:void 0,previewId:Xe?.id,trustedPreview:!!Xe&&!Xe.fork,allowedPreviewSecrets:dt?.inheritedSecrets}),N.warnings.some((wr)=>wr.code==="missing_required"))throw Error(`Required deployment configuration is unavailable: ${N.warnings.filter((wr)=>wr.code==="missing_required").map((wr)=>wr.key).join(", ")}`);if(Ce.operation.resourceId)for(let wr of Object.values(N.entries))go.setDependency({entryId:wr.id,resourceId:Ce.operation.resourceId,injectionTarget:"environment",required:wr.required,requiresRedeploy:!0});Ce.log(`Resolved configuration ${N.configurationHash.slice(0,18)} for ${Object.keys(N.values).length} keys.`,{stream:"system"})}let or=await np(I,{cwd:We,cliEntry:i,signal:Ce.signal,env:N?.values,onOutput:(Xe,dt)=>Ce.log(dt,{stream:Xe,step:"execute",secrets:[...wb,...Object.entries(N?.entries??{}).filter(([,Br])=>Br.kind==="secret").map(([Br])=>N.values[Br]).filter(Boolean)]})});if(or.ok&&Ce.operation.resourceId&&N)for(let Xe of Object.values(N.entries))go.setDependency({entryId:Xe.id,resourceId:Ce.operation.resourceId,injectionTarget:"environment",required:Xe.required,requiresRedeploy:!1,lastDeployedVersion:Xe.version});return await Hr?.(or.ok?"success":"failure",or.ok?`Preview is ready at ${String(we?.commitSha).slice(0,12)}`:`Preview deployment failed at ${String(we?.commitSha).slice(0,12)}`),or}catch(or){throw await Hr?.("error",`Preview deployment could not complete at ${String(we?.commitSha).slice(0,12)}`),or}finally{if(mt)Ss(mt,{recursive:!0,force:!0})}}}),...Mg({store:Er,executor:Ib}),...Hg({store:Ot,secrets:Ui,resolveAdapter:sp}),...Nf(ua,Oi.drivers),...th(Fo,[new Sl("aws","AWS regional execution requires an injected AwsRegionalTransport; topology and plans were preserved without provider mutation.")]),...Hf({store:qi,cleanup:up}),...la(Ad,kd),...qg({store:sr,queue:kt,resolveSource:hb,resolveDestination:yb,validateHealth:async(I,Ce)=>{if(!I.healthCheckId)return{healthy:!0,mode:"adapter"};let Ne=Ge.getHealthCheck(I.healthCheckId);if(!Ne||Ne.projectId!==I.projectId)return{healthy:!1,error:"Configured restore health check was not found."};let we=await new Oe(Ge).runAndEvaluate(Ne);return{healthy:we.result.status==="healthy",healthCheckId:Ne.id,healthResultId:we.result.id,target:Ce}}}),...Wp({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,Ce)=>{let Ne=Ge.listHealthChecks(Ce.projectId,Ce.environmentId).find((We)=>We.enabled&&We.name===I&&(!We.resourceId||We.resourceId===Ce.resourceId));if(!Ne)return{healthy:!1,message:`Named health gate ${I} was not found for this release.`};let we=await new Oe(Ge).runAndEvaluate(Ne);return{healthy:we.result.status==="healthy",evidence:{healthCheckId:Ne.id,healthResultId:we.result.id,status:we.result.status,timings:we.result.timings},message:we.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(_n(a),od(ct,ae(a,String(E)),O),rr)sd(a,rr.users),ry(ve,a,rr.users);let Bt=ey({cwd:t,enabled:ke,secret:Dt,authentication:ve,authorization:{store:a.store,organizationId:a.organization.id,projectId:a.project.id,defaultEnvironment:String(E)}}),ar=new Il,bp=setInterval(()=>ar.sweep(),60000);bp.unref?.();let Ja=new Ba,xd=new Ba(3,900000,900000),Wa=new Ba(8,900000,900000),Sp=setInterval(()=>Ja.prune(),300000),vp=setInterval(()=>xd.prune(),300000),wp=setInterval(()=>Wa.prune(),300000);if(Sp.unref?.(),vp.unref?.(),wp.unref?.(),ke){if(rr?.generated)console.warn(`
|
|
478
|
+
ts-cloud dashboard: created the first admin.
|
|
479
|
+
username: ${rr.generated.username}
|
|
480
|
+
password: ${rr.generated.password}
|
|
481
|
+
Saved (hashed) to ${Yh()}. This password is shown once.
|
|
482
|
+
`)}else console.warn(" ts-cloud dashboard: authentication is DISABLED (TS_CLOUD_DASHBOARD_AUTH=0). Every request runs as an admin.");let yo=r!=="127.0.0.1"&&r!=="localhost",Dd=(I)=>xT("sha256").update(`${Dt}:${I}`).digest("hex").slice(0,16),Cb=Kd({controlPlane:a.store,identities:pt,sources:Je,applications:{drafts:Jr,artifacts:vs,registries:Di}}),Ip=(I)=>I.headers.get("user-agent")?.trim().slice(0,256)||void 0,Ha=(I,Ce,Ne,we="local")=>ve.createSession({identityId:I,authMethod:we,userAgent:Ip(Ce),networkHint:Dd(Ne)}),Me=(I)=>{let Ce=a.store.getActorByExternalId("user",`dashboard:${I.username.toLowerCase()}`),Ne=Ce?a.store.getMembershipForActor(a.organization.id,Ce.id):void 0;return{actor:Ce,membership:Ne,grants:Ne?a.store.listGrants(Ne.id):[]}},ws=(I,Ce,Ne)=>{if(I.role==="admin")return!0;let we=a.store.getOperation(Ce),We=Me(I);if(!we||!We.membership)return!1;let mt=we.resourceId?{type:"resource",id:we.resourceId}:we.environmentId?{type:"environment",id:we.environmentId}:we.projectId?{type:"project",id:we.projectId}:{type:"organization"},N=a.store.resolveAuthorizationTarget(a.organization.id,mt);return!!N&&Z({membership:We.membership,grants:We.grants,capability:Ne,target:N}).allowed},Ar=(I,Ce,Ne)=>{if(I.role==="admin")return!0;let we=Me(I);if(!we.membership)return!1;let We=a.store.resolveAuthorizationTarget(a.organization.id,{type:"resource",id:Ce});return!!We&&Z({membership:we.membership,grants:we.grants,capability:Ne,target:We}).allowed},pa=(I,Ce,Ne)=>{if(I.role==="admin")return!0;let we=Me(I);if(!we.membership)return!1;let We=a.store.resolveAuthorizationTarget(a.organization.id,{type:"environment",id:Ce});return!!We&&Z({membership:we.membership,grants:we.grants,capability:Ne,target:We}).allowed},Ga=(I,Ce)=>{if(I.role==="admin")return!0;let Ne=Me(I);if(!Ne.membership)return!1;let we=a.store.resolveAuthorizationTarget(a.organization.id,{type:"organization"});return!!we&&Z({membership:Ne.membership,grants:Ne.grants,capability:Ce,target:we}).allowed},Is=Bun.serve({hostname:r,port:n,idleTimeout:30,websocket:{open(I){if(!pe){I.send(`The web terminal is disabled (TS_CLOUD_DASHBOARD_TERMINAL=0).\r
|
|
483
|
+
`),I.close();return}let Ce=Zy((Ne)=>I.send(Ne),{cwd:t,onExit:()=>{try{I.close()}catch{}}});J.set(I,Ce),I.send(`Connected to ${r==="127.0.0.1"?"localhost":r} shell. This is a line-oriented shell (no full-screen apps).\r
|
|
484
|
+
`)},message(I,Ce){J.get(I)?.write(typeof Ce==="string"?Ce:new TextDecoder().decode(Ce))},close(I){J.get(I)?.close(),J.delete(I)}},async fetch(I,Ce){let Ne=Date.now(),we=I.clone(),We=I.headers.get("x-request-id")?.slice(0,128)||crypto.randomUUID(),mt=!["GET","HEAD","OPTIONS"].includes(I.method.toUpperCase()),N=new URL(I.url),or=await(async()=>{let Xe=Ce??Is,dt=WT(r,Xe.port??n),Br=await Cb(I,Dd(Xe.requestIP(I)?.address??"unknown"));if(Br)return Br;let wr=N.searchParams.get("env"),ye=GT(m,E,wr),Mt=q.get(ye);if(!Mt)Mt=await at(ye);try{if(!XT(I))return S({ok:!1,error:"Cross-site requests are not allowed."},403);let Uo=/^\/api\/source\/webhooks\/([A-Za-z0-9_-]{16,200})$/.exec(N.pathname);if(Uo&&I.method==="POST"){let d=await ag({sources:Je,controlPlane:a.store,endpointToken:Uo[1],headers:I.headers,rawBody:new Uint8Array(await I.arrayBuffer())});return S({accepted:d.accepted,duplicate:d.duplicate,status:d.status,operationIds:d.operations.map((g)=>g.id),message:d.message},d.accepted?202:404)}let Es=/^\/auth\/oidc\/([a-z0-9-]+)\/(start|callback)$/.exec(N.pathname);if(Es&&I.method==="GET"){let[,d,g]=Es;if(!dt)return new Response(null,{status:302,headers:{location:"/login?sso_error=configuration"}});if(g==="start")try{let T=await iu(ve,d,dt,N.searchParams.get("return")??void 0,e.oidcFetch);return new Response(null,{status:302,headers:{location:T.authorizationUrl,"cache-control":"no-store"}})}catch(T){return a.store.appendEvent({organizationId:a.organization.id,type:"auth.oidc.start_failed",level:"warning",payload:{provider:d,reason:T instanceof Error?T.message.slice(0,200):"unknown"}}),new Response(null,{status:302,headers:{location:"/login?sso_error=start","cache-control":"no-store"}})}try{if(N.searchParams.has("error")){let K=ve.getOidcProviderBySlug(d),B=N.searchParams.get("state");if(K&&B)ve.consumeOidcTransaction(K.id,B);throw Error("OIDC provider returned an authorization error")}let T=await ou(ve,{providerSlug:d,state:N.searchParams.get("state")??"",code:N.searchParams.get("code")??"",origin:dt},e.oidcFetch),_=ny(ve,a,t,T.identity);ve.recordLogin(_.identity.id);let L=Ha(_.identity.id,I,Xe.requestIP(I)?.address??"unknown","oidc");return gi(),a.store.appendEvent({organizationId:a.organization.id,actorId:_.identity.actorId,type:"auth.login.succeeded",payload:{method:"oidc",provider:d,provisioned:_.provisioned}}),new Response(null,{status:302,headers:{location:T.returnPath,"cache-control":"no-store","set-cookie":ea(L.token,{secure:yo,maxAgeMs:Co})}})}catch(T){return a.store.appendEvent({organizationId:a.organization.id,type:"auth.oidc.callback_failed",level:"warning",payload:{provider:d,reason:T instanceof Error?T.message.slice(0,200):"unknown"}}),new Response(null,{status:302,headers:{location:"/login?sso_error=callback","cache-control":"no-store"}})}}if(N.pathname==="/api/invitations/accept"&&I.method==="POST"){let d=await oe(I),g=String(d.token??"").trim(),T=String(d.username??"").trim(),_=String(d.password??"");if(!g||!fd(T)||_.length<12)return S({ok:!1,error:"Invitation token, valid username, and a password of at least 12 characters are required."},422);let L=a.store.inspectInvitationToken(g);if(!L||L.state!=="pending")return S({ok:!1,error:L?`Invitation is ${L.state}`:"Invitation is invalid"},L?409:404);let K=pi(Jn(t),T),B=ve.getIdentityByUsername(T);if(K&&!Ti(_,B?.passwordHash??K.passwordHash))return S({ok:!1,error:"That username already exists; enter its current password to continue."},401);let Q=ve.getIdentityByEmail(L.email);if(Q&&Q.id!==B?.id)return S({ok:!1,error:"This invitation belongs to an existing account. Sign in with that account or ask an owner to resend it."},409);let fe=La(t,{username:T,password:K?void 0:_,name:typeof d.name==="string"?d.name:void 0,email:L.email,sites:K?.sites??{}}),ue=mr(a.store,fe.user);try{let He=a.store.acceptInvitation(g,ue.id),be=B?ve.setVerifiedEmail(B.id,He.invitation.email):ve.createIdentity({actorId:ue.id,username:fe.user.username,email:He.invitation.email,emailVerified:!0,passwordHash:fe.user.passwordHash}),Le=Ha(be.id,I,Xe.requestIP(I)?.address??"unknown");return gi(),S({ok:!0,user:ta(fe.user),organization:a.organization,membership:He.membership},200,{"set-cookie":ea(Le.token,{secure:yo,maxAgeMs:Co})})}catch(He){if(!K)zl(t,fe.user.username);let be=He instanceof Error?He.message:"Invitation could not be accepted.";return S({ok:!1,error:be},be.includes("expired")||be.includes("revoked")||be.includes("accepted")?409:404)}}if(N.pathname==="/api/auth/password-reset/request"&&I.method==="POST"){let d=await oe(I),g=String(d.identifier??"").trim().toLowerCase(),T=Xe.requestIP(I)?.address??"unknown",_=xd.check(g,T),L=g.includes("@")?ve.getIdentityByEmail(g):ve.getIdentityByUsername(g);if(_.allowed)xd.recordFailure(g,T);if(_.allowed&&L?.email&&L.emailVerifiedAt&&!L.disabledAt){ve.revokeActionTokens(L.id,"password_reset");let K=ve.createActionToken(L.id,"password_reset"),B=`${N.origin}/reset-password?token=${encodeURIComponent(K.token)}`,Q=await Sa(o,{to:L.email,subject:"Reset your ts-cloud password",text:`Reset your ts-cloud password: ${B}
|
|
485
|
+
|
|
486
|
+
This link expires in one hour and can be used once.`});a.store.appendEvent({organizationId:a.organization.id,actorId:L.actorId,type:"auth.password_reset.requested",payload:{delivered:Q}})}return S({ok:!0,message:"If that account has a verified email, a reset link has been sent."},202)}if(N.pathname==="/api/auth/password-reset/complete"&&I.method==="POST"){let d=await oe(I),g=String(d.token??"").trim(),T=String(d.password??"");if(!g||T.length<12)return S({ok:!1,error:"A valid reset token and password of at least 12 characters are required."},422);try{let _=ve.consumeActionToken(g,"password_reset"),L=No(T),K=ve.updatePassword(_.identityId,L);return yd(t,K.username,L),a.store.appendEvent({organizationId:a.organization.id,actorId:K.actorId,type:"auth.password_reset.completed"}),S({ok:!0,message:"Password changed. Sign in again."},200,{"set-cookie":md({secure:yo})})}catch(_){let L=_ instanceof Error?_.message:"Password reset failed.";return S({ok:!1,error:L.replace("Action token","Reset link")},L.includes("consumed")||L.includes("expired")?409:404)}}if(N.pathname==="/api/login"&&I.method==="POST"){let d=await oe(I),g=String(d.username??"").trim(),T=String(d.password??""),_=Xe.requestIP(I)?.address??"unknown",L=Ja.check(g,_);if(!L.allowed)return S({ok:!1,error:`Too many failed attempts. Try again in ${Math.ceil((L.retryAfterSeconds??0)/60)} minute(s).`},429,{"retry-after":String(L.retryAfterSeconds??60)});let K=pi(Jn(t),g),B=ve.getIdentityByUsername(g),Q=B?.passwordHash??K?.passwordHash??JT;if(!(Ti(T,Q)&&!!K&&!!B&&!B.disabledAt))return Ja.recordFailure(g,_),S({ok:!1,error:"Incorrect username or password."},401);if(iy(ve,a,B))return S({ok:!1,error:"Single sign-on is required for this account."},403);Ja.recordSuccess(g,_);let ue=B,He=ue.requiresPasswordUpgrade||xh(ue.passwordHash);if(He){let Le=No(T);ue=ve.rehashPassword(ue.id,Le),yd(t,ue.username,Le)}if(ve.recordLogin(ue.id),ve.getMfaFactor(ue.id)?.state==="active"){let Le=ve.createMfaChallenge(ue.id,"login");return a.store.appendEvent({organizationId:a.organization.id,actorId:ue.actorId,type:"auth.mfa.challenge.created",payload:{purpose:"login"}}),S({ok:!0,mfaRequired:!0,challengeToken:Le.token,passwordUpgraded:He})}let be=Ha(ue.id,I,_);return a.store.appendEvent({organizationId:a.organization.id,actorId:ue.actorId,type:"auth.login.succeeded",payload:{method:"local"}}),S({ok:!0,user:ta(K),passwordUpgraded:He},200,{"set-cookie":ea(be.token,{secure:yo,maxAgeMs:Co})})}if(N.pathname==="/api/auth/mfa/complete"&&I.method==="POST"){let d=await oe(I),g=String(d.challengeToken??"").trim(),T=String(d.code??"").trim(),_=Xe.requestIP(I)?.address??"unknown",K=ve.inspectMfaChallengeToken(g,"login")?.identityId??"unknown-mfa",B=Wa.check(K,_);if(!B.allowed)return S({ok:!1,error:"Too many MFA attempts. Try again later."},429,{"retry-after":String(B.retryAfterSeconds??60)});try{let Q=ve.completeMfaChallenge(g,T,"login");Wa.recordSuccess(K,_);let fe=new Date().toISOString(),ue=ve.createSession({identityId:Q.identity.id,userAgent:Ip(I),networkHint:Dd(_),mfaAt:fe,recentAuthAt:fe});return a.store.appendEvent({organizationId:a.organization.id,actorId:Q.identity.actorId,type:"auth.mfa.succeeded",payload:{purpose:"login",method:Q.method}}),S({ok:!0},200,{"set-cookie":ea(ue.token,{secure:yo,maxAgeMs:Co})})}catch{return Wa.recordFailure(K,_),S({ok:!1,error:"Authenticator or recovery code is incorrect."},401)}}if(N.pathname==="/api/logout"&&I.method==="POST"){let d=Bt.resolveSession(I);if(d)ve.revokeSession(d.identityId,d.id);let g=md({secure:yo});if(I.headers.get("accept")?.includes("text/html"))return new Response(null,{status:302,headers:{location:"/login","set-cookie":g}});return S({ok:!0},200,{"set-cookie":g})}if(N.pathname==="/login"){let d=ve.listOidcProviders(a.organization.id).map((g)=>({slug:g.slug,name:g.name}));return new Response(oy(O?.mode==="serverless",d),{headers:{"content-type":"text/html; charset=utf-8"}})}if(N.pathname==="/forgot-password"||N.pathname==="/reset-password")return new Response(sy(N.pathname==="/reset-password"?"reset":"request"),{headers:{"content-type":"text/html; charset=utf-8"}});if(N.pathname==="/accept-invitation")return cb(xi,N.pathname);let de=Bt.resolveUser(I);if(!de){if(!N.pathname.startsWith("/api/")&&I.headers.get("accept")?.includes("text/html"))return new Response(null,{status:302,headers:{location:"/login"}});return S({ok:!1,error:"Sign in to continue."},401)}let si=po(de,ye);if(N.pathname==="/api/me"){let d=a.store.getActorByExternalId("user",`dashboard:${de.username.toLowerCase()}`),g=d?a.store.getMembershipForActor(a.organization.id,d.id):void 0,T=a.store.resolveAuthorizationTarget(a.organization.id,g?.scope??{type:"project",id:a.project.id})??a.store.resolveAuthorizationTarget(a.organization.id,{type:"project",id:a.project.id});return S({ok:!0,user:ta(de),authEnabled:ke,organization:a.organization,membership:g,capabilities:Zr({membership:g,grants:g?a.store.listGrants(g.id):[],target:T})})}if(N.pathname.startsWith("/api/")){let d=await ty(I,N.pathname),g=Bt.check(I,N.pathname,de,d);if(!g.ok)return S({ok:!1,error:g.error},g.status??403);if(ke&&tA.has(`${I.method.toUpperCase()} ${N.pathname}`)){let T=Bt.resolveSession(I);if(!T||!ve.isRecentlyAuthenticated(T))return S({ok:!1,error:"Recent authentication is required for this change.",stepUpRequired:!0},401)}}if(N.pathname==="/api/auth/security"&&I.method==="GET"){let d=Me(de),g=d.actor?ve.getIdentityByActor(d.actor.id):void 0,T=Bt.resolveSession(I);return S({identity:g?{username:g.username,email:g.email,emailVerifiedAt:g.emailVerifiedAt,requiresPasswordUpgrade:g.requiresPasswordUpgrade,lastLoginAt:g.lastLoginAt}:void 0,currentSessionId:T?.id,sessions:g?ve.listSessions(g.id,{includeInactive:!0}):[],mfa:g?{factor:ve.getMfaFactor(g.id),recoveryCodesRemaining:ve.remainingRecoveryCodes(g.id)}:void 0})}if(N.pathname==="/api/auth/oidc/providers"&&I.method==="GET")return S({providers:ve.listOidcProviders(a.organization.id,{includeDisabled:!0}),callbackOrigin:dt,callbackPattern:dt?`${dt}/auth/oidc/{slug}/callback`:void 0,localOwnerRecovery:!0});if(N.pathname==="/api/auth/oidc/providers"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=g.actor?ve.getIdentityByActor(g.actor.id):void 0,_=d.enforceSso===!0;if(_&&(!T?.emailVerifiedAt||ve.remainingRecoveryCodes(T.id)<1))return S({ok:!1,error:"Verify the owner email and generate MFA recovery codes before enforcing SSO."},409);try{let L=wd(d.defaultRole),K=ve.upsertOidcProvider({id:typeof d.id==="string"?d.id:void 0,organizationId:a.organization.id,slug:String(d.slug??""),name:String(d.name??""),issuer:String(d.issuer??""),clientId:String(d.clientId??""),clientSecret:typeof d.clientSecret==="string"&&d.clientSecret?d.clientSecret:void 0,scopes:Array.isArray(d.scopes)?d.scopes.map(String):void 0,allowedDomains:Array.isArray(d.allowedDomains)?d.allowedDomains.map(String):[],defaultRole:L&&L!=="owner"?L:void 0,enabled:d.enabled!==!1,enforceSso:_});return a.store.appendEvent({organizationId:a.organization.id,actorId:g.actor?.id,type:"auth.oidc.provider.configured",payload:{providerId:K.id,issuer:K.issuer,enabled:K.enabled,enforceSso:K.enforceSso}}),S({ok:!0,provider:K})}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"OIDC provider could not be saved."},422)}}if(N.pathname==="/api/auth/oidc/providers"&&I.method==="PATCH"){let d=await oe(I),g=ve.getOidcProvider(String(d.id??""));if(!g||g.organizationId!==a.organization.id)return S({ok:!1,error:"OIDC provider was not found."},404);let T=Me(de),_=ve.setOidcProviderEnabled(g.id,d.enabled===!0);return a.store.appendEvent({organizationId:a.organization.id,actorId:T.actor?.id,type:_.enabled?"auth.oidc.provider.enabled":"auth.oidc.provider.disabled",payload:{providerId:g.id}}),S({ok:!0,provider:_})}if(N.pathname==="/api/automation"&&I.method==="GET"){let d=pt.listServiceAccounts(a.organization.id,{includeDisabled:!0}).map((g)=>{let T=a.store.getMembershipForActor(a.organization.id,g.actorId),_=g.createdByActorId?a.store.getActor(g.createdByActorId):void 0,L=pt.listTokens(g.id,{includeInactive:!0}).map((K)=>({...K,createdBy:K.createdByActorId?a.store.getActor(K.createdByActorId):void 0}));return{account:g,createdBy:_,membership:T,tokens:L}});return S({accounts:d,apiBaseUrl:`${N.origin}/api/v1`,openApiUrl:`${N.origin}/api/v1/openapi.json`,tokenEnvironmentVariable:"TS_CLOUD_API_TOKEN"})}if(N.pathname==="/api/automation/service-accounts"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=wd(d.roleTemplate),_=Ua(d);if(!g.actor||!T||T==="owner"||!_)return S({ok:!1,error:"A non-owner role and valid organization scope are required."},422);try{let L=pt.createServiceAccount({organizationId:a.organization.id,slug:String(d.slug??""),name:String(d.name??""),description:typeof d.description==="string"?d.description:void 0,roleTemplate:T,scope:_,createdByActorId:g.actor.id});return S({ok:!0,...L},201)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Service account could not be created."},422)}}if(N.pathname==="/api/automation/service-accounts"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=pt.getServiceAccount(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Service account was not found."},404);return S({ok:!0,account:pt.disableServiceAccount(T.id,g.actor?.id)})}if(N.pathname==="/api/automation/tokens"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=pt.getServiceAccount(String(d.serviceAccountId??"")),_=Ua(d);if(!g.actor||!T||T.organizationId!==a.organization.id||!_||!Array.isArray(d.capabilities))return S({ok:!1,error:"Service account, explicit capabilities, and valid scope are required."},422);try{let L=pt.createToken({serviceAccountId:T.id,name:String(d.name??"API token"),capabilities:d.capabilities.map(String),scope:_,expiresAt:typeof d.expiresAt==="string"?d.expiresAt:void 0,createdByActorId:g.actor.id});return S({ok:!0,token:L.token,secret:L.secret,revealOnce:!0},201)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"API token could not be created."},422)}}if(N.pathname==="/api/automation/tokens/rotate"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=pt.getToken(String(d.id??"")),_=T?pt.getServiceAccount(T.serviceAccountId):void 0;if(!g.actor||!T||_?.organizationId!==a.organization.id)return S({ok:!1,error:"API token was not found."},404);try{let L=pt.rotateToken(T.id,g.actor.id);return S({ok:!0,token:L.token,secret:L.secret,revealOnce:!0,overlap:!0},201)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"API token could not be rotated."},409)}}if(N.pathname==="/api/automation/tokens"&&I.method==="DELETE"){let d=await oe(I),g=Me(de),T=pt.getToken(String(d.id??"")),_=T?pt.getServiceAccount(T.serviceAccountId):void 0;if(!T||_?.organizationId!==a.organization.id)return S({ok:!1,error:"API token was not found."},404);return S({ok:!0,token:pt.revokeToken(T.id,g.actor?.id)})}if(N.pathname==="/api/onboarding"&&I.method==="GET"){let d=Je.listConnections(a.organization.id);return S({drafts:Jr.list(a.project.id),artifacts:vs.list(a.project.id),registries:Di.list(a.organization.id),sourceConnections:d,repositories:d.flatMap((g)=>Je.listRepositories(g.id)),project:{id:a.project.id,slug:a.project.slug,name:a.project.name},environments:[...a.environments.values()].map((g)=>({id:g.id,slug:g.slug,name:g.name,kind:g.kind,region:g.region})),resources:a.store.listResources(a.project.id).filter((g)=>g.kind==="application").map((g)=>({id:g.id,slug:g.slug,name:g.name,environmentId:g.environmentId}))})}if(N.pathname==="/api/onboarding/detect"&&I.method==="POST"){let d=await oe(I);try{if(d.source?.kind==="git"){let _=Je.getConnection(String(d.source.connectionId??"")),L=Je.getRepository(String(d.source.repositoryId??""));if(!_||_.organizationId!==a.organization.id||!L||L.connectionId!==_.id)throw Error("Authorized Git repository was not found");let K=typeof d.source.deployKeyId==="string"?Je.getDeployKey(d.source.deployKeyId):void 0;if(K&&K.connectionId!==_.id)throw Error("Deploy key does not belong to this connection");let B=ip(Et(Cd(),"ts-cloud-onboarding-git-"));try{let Q=await Wd({remote:L.cloneUrl,destination:Et(B,"checkout"),ref:String(d.source.ref??L.defaultBranch),sparsePaths:Array.isArray(d.source.sparsePaths)?d.source.sparsePaths.map(String):void 0,binding:{id:"detection",projectId:a.project.id,connectionId:_.id,repositoryId:L.id,repositoryFullName:L.fullName,defaultBranch:L.defaultBranch,monorepoRoot:String(d.source.monorepoRoot??"."),includePaths:[],excludePaths:[],submodules:d.source.submodules===!0,cloneDepth:1,deployKeyId:K?.id,autoDeploy:!1,pullRequestPreviews:!1,status:"active",version:1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}},{credential:Je.getCredential(_.id),deployKey:K?{...K,privateKey:Je.getDeployPrivateKey(K.id)}:void 0,timeoutMs:120000});return S({ok:!0,commitSha:Q.commitSha,candidates:At(Pn(Q.directory))})}finally{Ss(B,{recursive:!0,force:!0})}}if(Array.isArray(d.files)){if(d.files.length>1e4)throw Error("Detection file-count limit exceeded");let _=d.files.map((L)=>({path:String(L.path??""),size:Number(L.size??0),content:typeof L.content==="string"?L.content.slice(0,262144):void 0}));return S({ok:!0,candidates:At(_)})}let g=NT(t,String(d.root??".")),T=_T(t,g);if(T===".."||T.startsWith(`..${$T}`))throw Error("Detection root must stay inside the project");return S({ok:!0,candidates:At(Pn(g))})}catch(g){return S({ok:!1,error:g instanceof Error?g.message:"Application detection failed."},422)}}if(N.pathname==="/api/onboarding/plan"&&I.method==="POST"){let d=await oe(I);try{return S({ok:!0,plan:se(d.draft,Array.isArray(d.suppliedSecretNames)?d.suppliedSecretNames.map(String):[])})}catch(g){return S({ok:!1,error:g instanceof Error?g.message:"Application plan could not be generated."},422)}}if(N.pathname==="/api/onboarding/drafts"&&I.method==="POST"){let d=await oe(I),g=Me(de);try{return S({ok:!0,draft:Jr.create({organizationId:a.organization.id,projectId:a.project.id,name:String(d.name??d.draft?.name??"Application draft"),draft:{...d.draft,projectId:a.project.id},step:d.step,suppliedSecretNames:Array.isArray(d.suppliedSecretNames)?d.suppliedSecretNames.map(String):[],actorId:g.actor?.id})},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Application draft could not be saved."},422)}}if(N.pathname==="/api/onboarding/drafts"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=Jr.get(String(d.id??""));if(!T||T.projectId!==a.project.id)return S({ok:!1,error:"Application draft was not found."},404);try{return S({ok:!0,draft:Jr.update(T.id,Number(d.version),{draft:{...d.draft,projectId:a.project.id},step:d.step,suppliedSecretNames:Array.isArray(d.suppliedSecretNames)?d.suppliedSecretNames.map(String):void 0,actorId:g.actor?.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Application draft could not be updated."},409)}}if(N.pathname==="/api/onboarding/artifacts"&&I.method==="POST"){let d=Me(de);if(Number(I.headers.get("content-length")??0)>104857600)return S({ok:!1,error:"Artifact exceeds the 100 MB upload limit."},413);try{let T=new Uint8Array(await I.arrayBuffer());return S({ok:!0,artifact:vs.create({organizationId:a.organization.id,projectId:a.project.id,filename:I.headers.get("x-artifact-filename")??"application.zip",bytes:T,actorId:d.actor?.id})},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Artifact could not be inspected."},422)}}if(N.pathname==="/api/onboarding/registries"&&I.method==="POST"){let d=await oe(I),g=Me(de);try{return S({ok:!0,registry:Di.create({organizationId:a.organization.id,provider:d.provider,name:String(d.name??"Container registry"),host:String(d.host??""),credential:d.token||d.password?{username:typeof d.username==="string"?d.username:void 0,password:typeof d.password==="string"?d.password:void 0,token:typeof d.token==="string"?d.token:void 0}:void 0,credentialExpiresAt:typeof d.credentialExpiresAt==="string"?d.credentialExpiresAt:void 0,actorId:g.actor?.id})},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Registry connection could not be created."},422)}}if(N.pathname==="/api/onboarding/registries"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=Di.get(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Registry connection was not found."},404);try{if(d.action==="test")return S({ok:!0,registry:await Di.test(T.id,{image:typeof d.image==="string"?d.image:void 0})});if(d.action==="rotate")return S({ok:!0,registry:Di.rotate(T.id,{username:typeof d.username==="string"?d.username:void 0,password:typeof d.password==="string"?d.password:void 0,token:typeof d.token==="string"?d.token:void 0},{expiresAt:typeof d.expiresAt==="string"?d.expiresAt:void 0,actorId:g.actor?.id})});return S({ok:!1,error:"Registry action must be test or rotate."},422)}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Registry connection could not be updated."},422)}}if(N.pathname==="/api/onboarding/registries"&&I.method==="DELETE"){let d=await oe(I),g=Me(de),T=Di.get(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Registry connection was not found."},404);let _=Jr.list(a.project.id).filter((L)=>L.input.source.kind==="image"&&L.input.source.registryConnectionId===T.id||L.input.build.kind==="prebuilt_image"&&L.input.build.registryConnectionId===T.id);if(d.preview===!0)return S({ok:!0,preview:!0,affectedDrafts:_});return S({ok:!0,registry:Di.disconnect(T.id,g.actor?.id),affectedDrafts:_})}if(N.pathname==="/api/onboarding/apply"&&I.method==="POST"){let d=await oe(I),g=Me(de);try{let T=Nr({controlPlane:a.store,drafts:Jr,draftId:String(d.id??""),expectedVersion:Number(d.version),confirmEnvironment:String(d.confirmEnvironment??""),actorId:g.actor?.id});return S({ok:!0,resource:T.resource,operation:T.operation,plan:T.plan},202)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Application plan could not be applied."},422)}}if(N.pathname==="/api/sources"&&I.method==="GET"){let d=Je.listConnections(a.organization.id);return S({connections:d,bindings:Je.listBindings({projectId:a.project.id}),repositories:d.flatMap((g)=>Je.listRepositories(g.id)),deployKeys:d.flatMap((g)=>Je.listDeployKeys(g.id)),webhooks:d.flatMap((g)=>Je.listWebhooks(g.id)).map((g)=>({...g,deliveries:Je.listDeliveries(g.id,20)})),project:{id:a.project.id,slug:a.project.slug},environment:ae(a,String(ye)),resources:a.store.listResources(a.project.id,ae(a,String(ye)).environmentId).filter((g)=>g.kind==="application").map((g)=>({id:g.id,slug:g.slug,name:g.name}))})}if(N.pathname==="/api/sources/connections"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=String(d.provider??"");if(!["github","gitlab","bitbucket","gitea","generic_https","generic_ssh"].includes(T))return S({ok:!1,error:"A supported Git provider is required."},422);try{let _=T==="github"&&(d.privateKey||d.appId)?{appId:typeof d.appId==="string"?d.appId:void 0,installationId:typeof d.installationId==="string"?d.installationId:void 0,privateKey:typeof d.privateKey==="string"?d.privateKey:void 0}:T!=="generic_ssh"&&d.token?{token:typeof d.token==="string"?d.token:void 0,username:typeof d.username==="string"?d.username:void 0}:void 0,L={github:"https://github.com",gitlab:"https://gitlab.com",bitbucket:"https://bitbucket.org",gitea:"https://gitea.com"},K,B,Q;if(a.store.database.transaction(()=>{if(K=Je.createConnection({organizationId:a.organization.id,provider:T,name:String(d.name??T),host:String(d.host??L[T]??""),owner:typeof d.owner==="string"?d.owner:void 0,authKind:d.authKind,credential:_,grantedScopes:Array.isArray(d.grantedScopes)?d.grantedScopes.map(String):[],credentialExpiresAt:typeof d.credentialExpiresAt==="string"?d.credentialExpiresAt:void 0,createdByActorId:g.actor?.id}),typeof d.repositoryUrl==="string"&&typeof d.repositoryFullName==="string")B=Je.upsertRepository({connectionId:K.id,providerRepositoryId:`manual:${d.repositoryFullName}`,fullName:d.repositoryFullName,cloneUrl:d.repositoryUrl,defaultBranch:String(d.defaultBranch??"main"),visibility:"unknown",archived:!1,metadata:{source:"manual"}});if(T==="generic_ssh")Q=Je.createDeployKey({connectionId:K.id,name:String(d.deployKeyName??"Repository deploy key"),publicKey:String(d.publicKey??""),privateKey:String(d.deployPrivateKey??""),host:String(d.sshHost??""),hostKey:String(d.hostKey??""),actorId:g.actor?.id})})(),d.test===!0)K=await Hd(Je,K.id,B?.id);return S({ok:!0,connection:K,repository:B,deployKey:Q},201)}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Source connection could not be created."},422)}}if(N.pathname==="/api/sources/connections"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=Je.getConnection(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{if(d.action==="test")return S({ok:!0,connection:await Hd(Je,T.id,typeof d.repositoryId==="string"?d.repositoryId:void 0)});if(d.action==="rotate")return S({ok:!0,connection:Je.rotateCredential(T.id,{token:typeof d.token==="string"?d.token:void 0,username:typeof d.username==="string"?d.username:void 0,appId:typeof d.appId==="string"?d.appId:void 0,installationId:typeof d.installationId==="string"?d.installationId:void 0,privateKey:typeof d.privateKey==="string"?d.privateKey:void 0},{expiresAt:typeof d.expiresAt==="string"?d.expiresAt:void 0,actorId:g.actor?.id})});return S({ok:!1,error:"Connection action must be test or rotate."},422)}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Source connection could not be updated."},422)}}if(N.pathname==="/api/sources/connections"&&I.method==="DELETE"){let d=await oe(I),g=Me(de),T=Je.getConnection(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);let _=Je.listBindings({connectionId:T.id,status:"active"});if(d.preview===!0)return S({ok:!0,preview:!0,affectedBindings:_});return S({ok:!0,...Je.disconnectConnection(T.id,g.actor?.id)})}if(N.pathname==="/api/sources/deploy-keys"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=Je.getConnection(String(d.connectionId??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{return S({ok:!0,deployKey:Je.createDeployKey({connectionId:T.id,name:String(d.name??"Repository deploy key"),publicKey:String(d.publicKey??""),privateKey:String(d.privateKey??""),host:String(d.host??""),hostKey:String(d.hostKey??""),actorId:g.actor?.id})},201)}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Deploy key could not be stored."},422)}}if(N.pathname==="/api/sources/deploy-keys"&&I.method==="DELETE"){let d=await oe(I),g=Me(de),T=Je.getDeployKey(String(d.id??"")),_=T?Je.getConnection(T.connectionId):void 0;if(!T||!_||_.organizationId!==a.organization.id)return S({ok:!1,error:"Deploy key was not found."},404);let L=Je.listBindings({connectionId:_.id}).filter((K)=>K.deployKeyId===T.id);if(d.preview===!0)return S({ok:!0,preview:!0,affectedBindings:L});return S({ok:!0,...Je.revokeDeployKey(T.id,g.actor?.id)})}if(N.pathname==="/api/sources/repositories/sync"&&I.method==="POST"){let d=await oe(I),g=Je.getConnection(String(d.connectionId??""));if(!g||g.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{return S({ok:!0,repositories:await Pr(Je,String(d.connectionId??""),{search:typeof d.search==="string"?d.search:void 0})})}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Repositories could not be synchronized."},422)}}if(N.pathname==="/api/sources/references"&&I.method==="GET"){let d=Je.getConnection(String(N.searchParams.get("connectionId")??""));if(!d||d.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{return S(await Kt(Je,{connectionId:String(N.searchParams.get("connectionId")??""),repository:String(N.searchParams.get("repository")??""),repositoryId:N.searchParams.get("repositoryId")??void 0,deployKeyId:N.searchParams.get("deployKeyId")??void 0,type:N.searchParams.get("type")==="tags"?"tags":"branches",cursor:N.searchParams.get("cursor")??void 0}))}catch(g){return S({ok:!1,error:g instanceof Error?g.message:"References could not be listed."},422)}}if(N.pathname==="/api/sources/bindings"&&I.method==="POST"){let d=await oe(I),g=Me(de),T=ae(a,String(ye)),_=Je.getConnection(String(d.connectionId??""));if(!_||_.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{return S({ok:!0,binding:Je.createBinding({projectId:a.project.id,environmentId:T.environmentId,resourceId:typeof d.resourceId==="string"?d.resourceId:void 0,connectionId:String(d.connectionId??""),repositoryId:typeof d.repositoryId==="string"?d.repositoryId:void 0,repositoryFullName:String(d.repositoryFullName??""),defaultBranch:String(d.defaultBranch??"main"),branchRule:typeof d.branchRule==="string"?d.branchRule:void 0,tagRule:typeof d.tagRule==="string"?d.tagRule:void 0,monorepoRoot:String(d.monorepoRoot??"."),includePaths:Array.isArray(d.includePaths)?d.includePaths.map(String):[],excludePaths:Array.isArray(d.excludePaths)?d.excludePaths.map(String):[],submodules:d.submodules===!0,cloneDepth:d.cloneDepth?Number(d.cloneDepth):void 0,deployKeyId:typeof d.deployKeyId==="string"&&d.deployKeyId?d.deployKeyId:void 0,autoDeploy:d.autoDeploy!==!1,pullRequestPreviews:d.pullRequestPreviews!==!1,actorId:g.actor?.id})},201)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Source binding could not be created."},422)}}if(N.pathname==="/api/sources/bindings"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=Je.getBinding(String(d.id??""));if(!T||T.projectId!==a.project.id)return S({ok:!1,error:"Source binding was not found."},404);try{return S({ok:!0,binding:Je.updateBinding(T.id,Number(d.version),{defaultBranch:d.defaultBranch,branchRule:d.branchRule,tagRule:d.tagRule,monorepoRoot:d.monorepoRoot,includePaths:d.includePaths,excludePaths:d.excludePaths,submodules:d.submodules,cloneDepth:d.cloneDepth,deployKeyId:d.deployKeyId,autoDeploy:d.autoDeploy,pullRequestPreviews:d.pullRequestPreviews,status:d.status,disabledReason:d.disabledReason,actorId:g.actor?.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Source binding could not be updated."},409)}}if(N.pathname==="/api/sources/webhooks"&&I.method==="POST"){let d=await oe(I),g=Je.getConnection(String(d.connectionId??""));if(!g||g.organizationId!==a.organization.id)return S({ok:!1,error:"Source connection was not found."},404);try{let T=Je.createWebhook({connectionId:String(d.connectionId??""),repositoryId:typeof d.repositoryId==="string"?d.repositoryId:void 0,repositoryFullName:String(d.repositoryFullName??""),events:Array.isArray(d.events)?d.events.map(String):void 0,secret:typeof d.secret==="string"?d.secret:void 0}),_=process.env.TS_CLOUD_WEBHOOK_BASE_URL?.trim()||dt,L=_?Ct(_,T.webhook):void 0,K=d.reconcile!==!1&&_?await Jt(Je,T.webhook.id,_):T.webhook;return S({ok:!0,webhook:K,endpoint:L,endpointRevealOnce:!0},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Source webhook could not be created."},422)}}if(N.pathname==="/api/sources/webhooks"&&I.method==="PATCH"){let d=await oe(I),g=process.env.TS_CLOUD_WEBHOOK_BASE_URL?.trim()||dt,T=Je.getWebhook(String(d.id??"")),_=T?Je.getConnection(T.connectionId):void 0;if(!T||!_||_.organizationId!==a.organization.id)return S({ok:!1,error:"Source webhook was not found."},404);if(!g)return S({ok:!1,error:"Set TS_CLOUD_WEBHOOK_BASE_URL to reconcile provider webhooks."},422);try{return S({ok:!0,webhook:await Jt(Je,String(d.id??""),g)})}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Source webhook could not be reconciled."},422)}}if(N.pathname==="/api/sources/webhooks"&&I.method==="DELETE"){let d=await oe(I),g=Je.getWebhook(String(d.id??"")),T=g?Je.getConnection(g.connectionId):void 0;if(!g||!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Source webhook was not found."},404);try{return S({ok:!0,webhook:await wi(Je,String(d.id??""))})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Source webhook could not be removed."},422)}}if(N.pathname==="/api/security/posture"&&I.method==="GET"){let d=ae(a,String(ye)),g=ct.listFindings({...d,limit:500});return S({scope:d,summary:ct.summary(d.organizationId,d.projectId,d.environmentId),findings:g,scans:ct.listScanRuns({...d,limit:100}),policies:ct.listPolicies(d.organizationId).filter((T)=>!T.environmentId||T.environmentId===d.environmentId),waivers:g.flatMap((T)=>ct.listWaivers(T.id)),decisions:ct.listDecisions(d.environmentId,50),actors:a.store.listMemberships(a.organization.id).map((T)=>a.store.getActor(T.actorId)).filter(Boolean)})}if(N.pathname==="/api/security/export"&&I.method==="GET")return S(ct.exportPosture(a.organization.id));if(N.pathname==="/api/security/scan"&&I.method==="POST"){let d=ae(a,String(ye)),g=await new ps(ct).run(new Oa,{...d,artifactRoot:t}),T=od(ct,d,Mt??{});return S({ok:!0,source:g,host:T,summary:ct.summary(d.organizationId,d.projectId,d.environmentId)})}if(N.pathname==="/api/security/review"&&I.method==="POST")try{let d=ae(a,String(ye));return S({ok:!0,...Yt(ct,{scope:d,desiredConfigHash:a.project.desiredConfigHash})})}catch(d){return S({ok:!1,error:d instanceof Error?d.message:"Security change review failed."},409)}if(N.pathname==="/api/security/policies"&&I.method==="POST"){let d=await oe(I),g=Me(de);if(!g.actor)return S({ok:!1,error:"An organization actor is required."},403);try{let T=ct.createPolicy({organizationId:a.organization.id,environmentId:d.environmentId===null?void 0:String(d.environmentId??ae(a,String(ye)).environmentId),name:String(d.name??""),scannerFailMode:d.scannerFailMode==="open"?"open":"closed",requiredScanners:Array.isArray(d.requiredScanners)?d.requiredScanners.map(String):[],rules:Array.isArray(d.rules)?d.rules.map((_)=>({minimumSeverity:String(_.minimumSeverity),action:String(_.action),scannerId:_.scannerId?String(_.scannerId):void 0})):[],actorId:g.actor.id});return S({ok:!0,policy:T},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Security policy could not be created."},422)}}if(N.pathname==="/api/security/policies"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=ct.getPolicy(String(d.id??""));if(!g.actor||!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Security policy was not found."},404);try{return S({ok:!0,policy:ct.updatePolicy(T.id,Number(d.version),{name:typeof d.name==="string"?d.name:void 0,scannerFailMode:d.scannerFailMode==="open"||d.scannerFailMode==="closed"?d.scannerFailMode:void 0,requiredScanners:Array.isArray(d.requiredScanners)?d.requiredScanners.map(String):void 0,rules:Array.isArray(d.rules)?d.rules.map((_)=>({minimumSeverity:String(_.minimumSeverity),action:String(_.action),scannerId:_.scannerId?String(_.scannerId):void 0})):void 0,enabled:typeof d.enabled==="boolean"?d.enabled:void 0,actorId:g.actor.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Security policy could not be updated."},409)}}if(N.pathname==="/api/security/waivers"&&I.method==="POST"){let d=await oe(I),g=Me(de);if(!g.actor)return S({ok:!1,error:"An organization actor is required."},403);try{return S({ok:!0,waiver:ct.createWaiver({findingId:String(d.findingId??""),policyId:typeof d.policyId==="string"?d.policyId:void 0,reason:String(d.reason??""),referenceUrl:typeof d.referenceUrl==="string"?d.referenceUrl:void 0,expiresAt:String(d.expiresAt??""),actorId:g.actor.id})},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Security waiver could not be created."},422)}}if(N.pathname==="/api/security/waivers"&&I.method==="DELETE"){let d=await oe(I),g=Me(de);if(!g.actor)return S({ok:!1,error:"An organization actor is required."},403);try{return S({ok:!0,waiver:ct.revokeWaiver(String(d.id??""),g.actor.id)})}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Security waiver could not be revoked."},404)}}if(N.pathname==="/api/security/findings"&&I.method==="PATCH"){let d=await oe(I),g=Me(de),T=ct.getFinding(String(d.id??""));if(!g.actor||!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Security finding was not found."},404);try{let _=d.action==="acknowledge"?ct.acknowledgeFinding(T.id,g.actor.id):ct.assignFinding(T.id,typeof d.ownerActorId==="string"&&d.ownerActorId?d.ownerActorId:void 0,g.actor.id);return S({ok:!0,finding:_})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Security finding could not be updated."},422)}}if(N.pathname==="/api/security/comments"&&I.method==="POST"){let d=await oe(I),g=Me(de);if(!g.actor)return S({ok:!1,error:"An organization actor is required."},403);try{return S({ok:!0,comment:ct.addComment({findingId:String(d.findingId??""),actorId:g.actor.id,body:String(d.body??""),referenceUrl:typeof d.referenceUrl==="string"?d.referenceUrl:void 0})},201)}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Comment could not be saved."},422)}}if(N.pathname==="/api/auth/sessions"&&I.method==="GET"){let d=Bt.resolveSession(I);return S({currentSessionId:d?.id,sessions:d?ve.listSessions(d.identityId,{includeInactive:!0}):[]})}if(N.pathname==="/api/auth/sessions"&&I.method==="DELETE"){let d=await oe(I),g=Bt.resolveSession(I);if(!g)return S({ok:!1,error:"Sign in again to manage sessions."},401);let T=String(d.id??""),_=ve.revokeSession(g.identityId,T),L=T===g.id&&_?{"set-cookie":md({secure:yo})}:void 0;return S({ok:_,signedOut:T===g.id&&_},_?200:404,L)}if(N.pathname==="/api/auth/sessions/revoke-others"&&I.method==="POST"){let d=Bt.resolveSession(I);if(!d)return S({ok:!1,error:"Sign in again to manage sessions."},401);return S({ok:!0,revoked:ve.revokeOtherSessions(d.identityId,d.id)})}if(N.pathname==="/api/auth/password/change"&&I.method==="POST"){let d=await oe(I),g=String(d.currentPassword??""),T=String(d.password??""),_=Me(de),L=_.actor?ve.getIdentityByActor(_.actor.id):void 0;if(!L||!Ti(g,L.passwordHash))return S({ok:!1,error:"Current password is incorrect."},401);if(T.length<12)return S({ok:!1,error:"New password must be at least 12 characters."},422);if(Ti(T,L.passwordHash))return S({ok:!1,error:"Choose a different password."},409);let K=No(T),B=ve.updatePassword(L.id,K);yd(t,B.username,K);let Q=Ha(B.id,I,Xe.requestIP(I)?.address??"unknown");return a.store.appendEvent({organizationId:a.organization.id,actorId:B.actorId,type:"auth.password.changed"}),S({ok:!0,message:"Password changed and other sessions were signed out."},200,{"set-cookie":ea(Q.token,{secure:yo,maxAgeMs:Co})})}if(N.pathname==="/api/auth/mfa/enroll"&&I.method==="POST"){let d=await oe(I),g=Bt.resolveSession(I),T=Me(de),_=T.actor?ve.getIdentityByActor(T.actor.id):void 0;if(!g||!_)return S({ok:!1,error:"Sign in again before enabling MFA."},401);if(!Ti(String(d.password??""),_.passwordHash))return S({ok:!1,error:"Current password is incorrect."},401);try{let L=ve.beginTotpEnrollment(_.id,{issuer:a.organization.name});return a.store.appendEvent({organizationId:a.organization.id,actorId:_.actorId,type:"auth.mfa.enrollment.started"}),S({factor:L.factor,secret:L.secret,uri:L.uri})}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"MFA enrollment failed."},409)}}if(N.pathname==="/api/auth/mfa/verify"&&I.method==="POST"){let d=await oe(I),g=Bt.resolveSession(I),T=Me(de),_=T.actor?ve.getIdentityByActor(T.actor.id):void 0;if(!g||!_)return S({ok:!1,error:"Sign in again before enabling MFA."},401);try{let L=ve.verifyTotpEnrollment(_.id,String(d.code??""));return ve.markSessionStepUp(g.id,!0),a.store.appendEvent({organizationId:a.organization.id,actorId:_.actorId,type:"auth.mfa.enabled",payload:{recoveryCodeCount:L.recoveryCodes.length}}),S(L)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"MFA enrollment failed."},422)}}if(N.pathname==="/api/auth/mfa"&&I.method==="DELETE"){let d=await oe(I),g=Bt.resolveSession(I),T=Me(de),_=T.actor?ve.getIdentityByActor(T.actor.id):void 0;if(!g||!_||!Ti(String(d.password??""),_.passwordHash))return S({ok:!1,error:"Current password is incorrect."},401);let L=ve.verifyMfaCode(_.id,String(d.code??""));if(!L.valid||!L.method)return S({ok:!1,error:"Authenticator or recovery code is incorrect."},401);return ve.disableMfa(_.id),ve.revokeOtherSessions(_.id,g.id),ve.markSessionStepUp(g.id),a.store.appendEvent({organizationId:a.organization.id,actorId:_.actorId,type:"auth.mfa.disabled",payload:{method:L.method}}),S({ok:!0})}if(N.pathname==="/api/auth/step-up"&&I.method==="POST"){let d=await oe(I),g=Bt.resolveSession(I),T=Me(de),_=T.actor?ve.getIdentityByActor(T.actor.id):void 0;if(!g||!_||!Ti(String(d.password??""),_.passwordHash))return S({ok:!1,error:"Current password is incorrect."},401);let L=ve.getMfaFactor(_.id);if(L?.state==="active"){if(!ve.verifyMfaCode(_.id,String(d.code??"")).valid)return S({ok:!1,error:"Authenticator or recovery code is incorrect."},401)}let K=ve.markSessionStepUp(g.id,L?.state==="active");return a.store.appendEvent({organizationId:a.organization.id,actorId:_.actorId,type:"auth.step_up.succeeded",payload:{mfa:L?.state==="active"}}),S({ok:!0,recentAuthAt:K.recentAuthAt})}if(N.pathname==="/api/terminal"){if(!pe)return S({ok:!1,error:"The web terminal is disabled."},403);if(Xe.upgrade(I))return;return Ed("WebSocket upgrade failed",400)}if(N.pathname==="/api/health"){let d=a.store.health();return S({ok:!0,cwd:t,environment:ye,environments:m,uiRoot:await Pi(de,ye),liveData:Te.size>0,terminal:pe,localPackage:import.meta.url.includes("/Code/Libraries/ts-cloud/"),controlPlane:{schemaVersion:d.schemaVersion,supportedSchemaVersion:d.supportedSchemaVersion,integrity:d.integrity,pendingRetryableOperations:d.pendingRetryableOperations}})}if(N.pathname==="/api/control-plane/operations"){let d=N.searchParams.get("state"),g=d&&["queued","running","succeeded","failed","cancelled","timed_out"].includes(d)?d:void 0;return S({operations:a.store.listOperations({projectId:a.project.id,state:g,kind:N.searchParams.get("kind")??void 0,limit:Number(N.searchParams.get("limit"))||100})})}if(N.pathname==="/api/queue"&&I.method==="GET"){let d=N.searchParams.get("state"),g=d&&["queued","running","succeeded","failed","cancelled","timed_out"].includes(d)?d:void 0,T=kt.list({projectId:a.project.id,state:g,limit:Number(N.searchParams.get("limit"))||250}).filter((_)=>ws(de,_.operation.id,"deployments:read")).map((_)=>{let L=_.operation.resourceId?a.store.getResource(_.operation.resourceId):void 0,K=_.operation.environmentId?a.store.listEnvironments(a.project.id).find((fe)=>fe.id===_.operation.environmentId):void 0,B=_.operation.actorId?a.store.getActor(_.operation.actorId):void 0,Q=_.operation.input;return{..._,target:L?{id:L.id,name:L.name,slug:L.slug,kind:L.kind}:K?{id:K.id,name:K.name,slug:K.slug,kind:"environment"}:{id:a.project.id,name:a.project.name,slug:a.project.slug,kind:"project"},actor:B?{id:B.id,name:B.displayName,kind:B.kind}:void 0,commit:Q.revision??Q.source?.commitSha??null}});return S({operations:T,concurrency:kt.limits})}if(N.pathname==="/api/queue/logs"&&I.method==="GET"){let d=String(N.searchParams.get("id")??"");if(!ws(de,d,"deployments:read"))return S({ok:!1,error:"Operation was not found in this scope."},404);let g=kt.logs(d,{after:Number(N.searchParams.get("after"))||0,limit:Number(N.searchParams.get("limit"))||500});return S({entries:g,cursor:g.at(-1)?.sequence??(Number(N.searchParams.get("after"))||0),operation:a.store.getOperation(d)})}if(N.pathname==="/api/queue/stream"&&I.method==="GET"){let d=String(N.searchParams.get("id")??"");if(!ws(de,d,"deployments:read"))return S({ok:!1,error:"Operation was not found in this scope."},404);let g=I.headers.get("last-event-id")?.trim(),T=Number(g||N.searchParams.get("after")||0),_=new TextEncoder,L,K=!1,B=new ReadableStream({start(Q){let fe=()=>{if(K)return;let ue=Bt.resolveUser(I);if(!ue||!ws(ue,d,"deployments:read")){if(K=!0,L)clearInterval(L);Q.close();return}let He=kt.logs(d,{after:T,limit:500});for(let Le of He)T=Le.sequence,Q.enqueue(_.encode(`id: ${Le.sequence}
|
|
487
|
+
event: log
|
|
488
|
+
data: ${JSON.stringify(Le)}
|
|
489
|
+
|
|
490
|
+
`));let be=a.store.getOperation(d);if(be&&["succeeded","failed","cancelled","timed_out"].includes(be.state)&&kt.logs(d,{after:T,limit:1}).length===0){if(K=!0,L)clearInterval(L);Q.enqueue(_.encode(`event: complete
|
|
491
|
+
data: ${JSON.stringify({state:be.state,cursor:T})}
|
|
492
|
+
|
|
493
|
+
`)),Q.close()}};if(fe(),!K)L=setInterval(fe,500);I.signal.addEventListener("abort",()=>{if(K=!0,L)clearInterval(L);try{Q.close()}catch{}},{once:!0})},cancel(){if(K=!0,L)clearInterval(L)}});return new Response(B,{headers:{"content-type":"text/event-stream","cache-control":"no-store","x-accel-buffering":"no"}})}if(N.pathname==="/api/queue/cancel"&&I.method==="POST"){let d=await oe(I),g=String(d.id??"");if(!ws(de,g,"deployments:cancel"))return S({ok:!1,error:"Operation was not found or cannot be cancelled in this scope."},404);let T=mr(a.store,de);try{return S({ok:!0,operation:kt.requestCancellation(g,T.id)})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Cancellation failed."},409)}}if(N.pathname==="/api/queue/retry"&&I.method==="POST"){let d=await oe(I),g=String(d.id??"");if(!ws(de,g,"deployments:create"))return S({ok:!1,error:"Operation was not found or cannot be retried in this scope."},404);let T=mr(a.store,de);try{return S({ok:!0,operation:kt.retry(g,String(d.errorClass??"manual"),{delayMs:Number(d.delayMs)||0,actorId:T.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Retry failed."},409)}}if(N.pathname==="/api/queue/settings"&&I.method==="GET")return S({concurrency:kt.limits});if(N.pathname==="/api/queue/settings"&&I.method==="PATCH"){let d=await oe(I);if(d.confirm!=="update queue limits")return S({ok:!1,error:'Type "update queue limits" to confirm production concurrency changes.'},409);let g=mr(a.store,de);return S({ok:!0,concurrency:kt.configureConcurrency(d.concurrency??{},{organizationId:a.organization.id,actorId:g.id})})}if(N.pathname==="/api/queue/history"&&I.method==="DELETE"){let d=await oe(I);if(d.confirm!=="clear completed")return S({ok:!1,error:'Type "clear completed" to confirm retained history cleanup.'},409);let g=mr(a.store,de);return S({ok:!0,deleted:kt.clearCompleted({projectId:a.project.id,before:typeof d.before==="string"?d.before:void 0,actorId:g.id})})}if(N.pathname==="/api/previews"&&I.method==="GET"){let d=nr.previews.listInstances({projectId:a.project.id}).filter((_)=>Ar(de,_.resourceId,"deployments:read")),g=nr.previews.listDefinitions(a.project.id).filter((_)=>Ar(de,_.resourceId,"project:read")),T=a.store.listResources(a.project.id).filter((_)=>_.kind==="application"&&Ar(de,_.id,"project:read")).map((_)=>({id:_.id,slug:_.slug,name:_.name,environmentId:_.environmentId}));return S({previews:d,definitions:g,resources:T,environments:[...a.environments.values()]})}if(N.pathname==="/api/releases"&&I.method==="GET"){let d=[...a.environments.values()],g=a.store.listResources(a.project.id).filter((L)=>Ar(de,L.id,"deployments:read")),T=new Set(g.map((L)=>L.id)),_=ii.releases.list({projectId:a.project.id}).filter((L)=>T.has(L.resourceId)).map((L)=>{let K=g.find((fe)=>fe.id===L.resourceId),B=d.find((fe)=>fe.id===L.environmentId),Q=L.previousReleaseId?ii.releases.get(L.previousReleaseId):void 0;return{...L,resource:K?{id:K.id,name:K.name,slug:K.slug,provider:K.provider}:void 0,environment:B?{id:B.id,name:B.name,slug:B.slug,kind:B.kind}:void 0,artifact:ii.releases.getArtifact(L.artifactId),transitions:ii.releases.transitions(L.id),approvals:ii.releases.approvals(L.id),previous:Q,comparison:Q?ii.releases.compare(Q.id,L.id):void 0,capabilities:Qt({kind:L.kind,provider:K?.provider,hasHealthGate:!!L.healthGate,replicas:Number(L.manifest?.replicas)||1})}});return S({releases:_,resources:g.map((L)=>({id:L.id,name:L.name,slug:L.slug,environmentId:L.environmentId,provider:L.provider})),environments:d})}if(N.pathname==="/api/releases/action"&&I.method==="POST"){let d=await oe(I),g=ii.releases.get(String(d.id??"")),T=String(d.action??"");if(!g||!Ar(de,g.resourceId,"deployments:create"))return S({ok:!1,error:"Release was not found in this scope."},404);let _=mr(a.store,de);try{if(T==="activate")return S({ok:!0,operation:ii.enqueueActivation(g,{actorId:_.id})});if(T==="rollback"){let L=a.store.getResource(g.resourceId);if(d.confirm!==L?.slug)return S({ok:!1,error:`Type "${L?.slug??""}" to confirm rollback.`},409);return S({ok:!0,operation:ii.enqueueRollback(g,{actorId:_.id,targetReleaseId:typeof d.targetReleaseId==="string"?d.targetReleaseId:void 0})})}if(T==="approve"){let L=a.store.listEnvironments(g.projectId).find((K)=>K.id===g.environmentId);if(d.confirm!==L?.slug)return S({ok:!1,error:`Type "${L?.slug??""}" to confirm the environment gate.`},409);return S({ok:!0,release:ii.releases.approve(g.id,{actorId:_.id,decision:d.decision==="rejected"?"rejected":"approved",comment:typeof d.comment==="string"?d.comment:void 0})})}if(T==="pin")return S({ok:!0,release:ii.releases.pin(g.id,d.pinned!==!1,typeof d.reason==="string"?d.reason:void 0)});if(T==="promote"){let L=a.store.getResource(String(d.targetResourceId??"")),K=L?a.store.listEnvironments(g.projectId).find((B)=>B.id===L.environmentId):void 0;if(!L||!K||!Ar(de,L.id,"deployments:create"))return S({ok:!1,error:"Promotion target was not found in this scope."},404);if(d.confirm!==K.slug)return S({ok:!1,error:`Type "${K.slug}" to confirm promotion.`},409);return S({ok:!0,release:ii.releases.promote(g.id,{targetEnvironmentId:K.id,targetResourceId:L.id,config:d.config&&typeof d.config==="object"?d.config:{},strategy:typeof d.strategy==="string"?d.strategy:void 0,actorId:_.id,approvalRequired:d.approvalRequired===!0})})}return S({ok:!1,error:"Unsupported release action."},422)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Release action failed."},409)}}if(N.pathname==="/api/compose"&&I.method==="GET"){let d=ho.applications.list({projectId:a.project.id}).filter((g)=>Ar(de,g.resourceId,"applications:read")).map((g)=>({...g,services:ho.applications.services(g.id)}));return S({applications:d,templates:er(),environments:[...a.environments.values()]})}if(N.pathname==="/api/compose/preview"&&I.method==="POST"){let d=await oe(I),g=String(d.environmentId??"");if(!pa(de,g,"applications:manage"))return S({ok:!1,error:"Environment was not found in this scope."},404);try{return S({ok:!0,result:ho.applications.preview(String(d.source??""),{name:String(d.name??""),slug:typeof d.slug==="string"?d.slug:void 0,projectId:a.project.id,environmentId:g})})}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Compose could not be parsed."},422)}}if((N.pathname==="/api/compose/import"||N.pathname==="/api/compose/template")&&I.method==="POST"){let d=await oe(I),g=String(d.environmentId??"");if(!pa(de,g,"applications:manage"))return S({ok:!1,error:"Environment was not found in this scope."},404);let T=mr(a.store,de);try{let _=N.pathname.endsWith("/template")?ho.applications.fromTemplate(String(d.templateId??""),d.inputs&&typeof d.inputs==="object"?d.inputs:{},{name:String(d.name??""),projectId:a.project.id,environmentId:g,version:typeof d.templateVersion==="string"?d.templateVersion:void 0,createdByActorId:T.id}):ho.applications.import(String(d.source??""),{name:String(d.name??""),slug:typeof d.slug==="string"?d.slug:void 0,projectId:a.project.id,environmentId:g,createdByActorId:T.id});return S({ok:!0,application:_.application,diagnostics:_.parsed.diagnostics})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Compose application could not be saved."},422)}}if(N.pathname==="/api/compose/action"&&I.method==="POST"){let d=await oe(I),g=ho.applications.get(String(d.id??"")),T=String(d.action??""),_=T==="delete"||T==="stop"?"deployments:cancel":"deployments:create";if(!g||!Ar(de,g.resourceId,_))return S({ok:!1,error:"Compose application was not found in this scope."},404);try{let L=mr(a.store,de);return S({ok:!0,operation:ho.enqueue(g,T,{actorId:L.id,service:typeof d.service==="string"?d.service:void 0,replicas:Number.isFinite(Number(d.replicas))?Number(d.replicas):void 0,removeVolumes:d.removeVolumes===!0,confirmation:typeof d.confirm==="string"?d.confirm:void 0})})}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Compose operation could not be queued."},409)}}if((N.pathname==="/api/compose/logs"||N.pathname==="/api/compose/shell")&&I.method==="POST"){let d=await oe(I),g=ho.applications.get(String(d.id??"")),T=N.pathname.endsWith("/shell"),_=T?"runtime:terminal":"runtime:logs";if(!g||!Ar(de,g.resourceId,_))return S({ok:!1,error:"Compose service was not found in this scope."},404);let L=String(d.service??"");if(!g.manifest.spec.services[L])return S({ok:!1,error:"Compose service was not found."},404);if(T&&d.confirm!==L)return S({ok:!1,error:`Type "${L}" to run a service command.`},409);let K=a.store.listEnvironments(g.projectId).find((Q)=>Q.id===g.environmentId)?.slug;if(!K)return S({ok:!1,error:"Compose environment was not found."},404);let B=T?Vn(g.manifest,L,Array.isArray(d.command)?d.command.map(String):["sh"]):jn(g.manifest,L,Number(d.lines)||200);return S(await Xt(o,K,B))}if(N.pathname==="/api/previews/definitions"&&I.method==="POST"){let d=await oe(I),g=String(d.resourceId??"");if(!Ar(de,g,"config:write"))return S({ok:!1,error:"Application was not found in this scope."},404);let T=mr(a.store,de);try{return S({ok:!0,definition:nr.previews.createDefinition({...d,projectId:a.project.id,resourceId:g,baseEnvironmentId:String(d.baseEnvironmentId??""),domainPattern:String(d.domainPattern??""),createdByActorId:T.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Preview policy could not be created."},409)}}if(N.pathname==="/api/previews/deploy"&&I.method==="POST"){let d=await oe(I),g=nr.previews.getDefinition(String(d.definitionId??""));if(!g||!Ar(de,g.resourceId,"deployments:create"))return S({ok:!1,error:"Preview policy was not found in this scope."},404);let T=mr(a.store,de);try{let _=nr.previews.upsert({definitionId:g.id,sourceProvider:"dashboard",repository:"dashboard",branch:String(d.branch??""),pullRequestNumber:Number(d.pullRequestNumber)||void 0,commitSha:String(d.commitSha??""),createdByActorId:T.id});return S({ok:!0,preview:_.preview,operation:nr.enqueueDeploy(_.preview,{created:_.created,actorId:T.id})})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Preview could not be queued."},409)}}if(N.pathname==="/api/previews/destroy"&&I.method==="POST"){let d=await oe(I),g=nr.previews.getInstance(String(d.id??""));if(!g||!Ar(de,g.resourceId,"deployments:cancel"))return S({ok:!1,error:"Preview was not found in this scope."},404);if(d.confirm!==g.name)return S({ok:!1,error:`Type "${g.name}" to confirm tagged teardown.`},409);let T=mr(a.store,de);return S({ok:!0,operation:nr.enqueueDestroy(g,"dashboard",T.id)})}if(N.pathname==="/api/previews/extend"&&I.method==="POST"){let d=await oe(I),g=nr.previews.getInstance(String(d.id??""));if(!g||!Ar(de,g.resourceId,"deployments:create"))return S({ok:!1,error:"Preview was not found in this scope."},404);return S({ok:!0,preview:nr.previews.extend(g.id,Number(d.hours))})}if(N.pathname==="/api/previews/rebuild"&&I.method==="POST"){let d=await oe(I),g=nr.previews.getInstance(String(d.id??""));if(!g||!Ar(de,g.resourceId,"deployments:create"))return S({ok:!1,error:"Preview was not found in this scope."},404);let T=mr(a.store,de);return S({ok:!0,operation:nr.enqueueDeploy(g,{actorId:T.id,reason:"manual_rebuild"})})}if(N.pathname==="/api/previews/cleanup"&&I.method==="POST"){let d=await oe(I);if(!d.dryRun&&d.confirm!=="cleanup previews")return S({ok:!1,error:'Type "cleanup previews" to confirm teardown.'},409);let g=mr(a.store,de);return S({ok:!0,...nr.cleanup({dryRun:d.dryRun===!0,maxAgeHours:Number(d.maxAgeHours)||void 0,keepCount:Number(d.keepCount)||void 0,actorId:g.id})})}if(N.pathname==="/api/control-plane/events")return S({events:a.store.listEvents({organizationId:a.organization.id,projectId:a.project.id,operationId:N.searchParams.get("operationId")??void 0,correlationId:N.searchParams.get("correlationId")??void 0,afterSequence:Number(N.searchParams.get("afterSequence"))||void 0,limit:Number(N.searchParams.get("limit"))||200})});if(N.pathname==="/api/search"){let d=String(N.searchParams.get("q")??"").trim().slice(0,128),g=si.role==="member"?new Set(Object.keys(si.sites)):void 0,T=d?Cs(a.store,{projectId:a.project.id,query:d,allowedResourceSlugs:g,limit:Number(N.searchParams.get("limit"))||20}):[];return S({query:d,results:T,stale:!1})}if(N.pathname==="/api/search/preferences"&&I.method==="GET"){let d=`dashboard:${de.username.toLowerCase()}`;return S({savedFilters:a.store.listSavedFilters(d),navigation:a.store.listNavigation(d)})}if(N.pathname==="/api/search/preferences"&&I.method==="POST"){let d=`dashboard:${de.username.toLowerCase()}`,g=await oe(I),T=String(g.action??"");if(T==="save-filter")return S({savedFilter:a.store.saveFilter(d,String(g.name??""),String(g.routeId??""),g.query??{})});if(T==="favorite")return S({navigation:a.store.setFavorite(d,String(g.entityType??""),String(g.entityId??""),g.favorite!==!1)});if(T==="visit")return S({navigation:a.store.recordNavigation(d,String(g.entityType??""),String(g.entityId??""))});return S({ok:!1,error:"Unknown search preference action."},422)}if(N.pathname==="/api/search/preferences"&&I.method==="DELETE"){let d=`dashboard:${de.username.toLowerCase()}`,g=await oe(I);return S({ok:a.store.deleteSavedFilter(d,String(g.id??""))})}if(N.pathname==="/api/organization"&&I.method==="GET"){let d=a.store.listMemberships(a.organization.id,{includeRevoked:!0}).map((g)=>{let T=a.store.getActor(g.actorId);return{...g,actor:T?{id:T.id,displayName:T.displayName,externalId:T.externalId,disabledAt:T.disabledAt}:void 0,grants:a.store.listGrants(g.id)}});return S({organization:a.organization,project:a.project,environments:a.store.listEnvironments(a.project.id),resources:a.store.listResources(a.project.id).map((g)=>({id:g.id,environmentId:g.environmentId,kind:g.kind,slug:g.slug,name:g.name})),memberships:d,invitations:a.store.listInvitations(a.organization.id)})}if(N.pathname==="/api/organization/invitations"&&I.method==="GET")return S({invitations:a.store.listInvitations(a.organization.id)});if(N.pathname==="/api/organization/invitations"&&I.method==="POST"){let d=await oe(I),g=wd(d.roleTemplate),T=Ua(d);if(!g||!T)return S({ok:!1,error:"Choose a valid role template and resource scope."},422);let _=Me(de);if(!_.actor||!_.membership)return S({ok:!1,error:"Your organization membership is unavailable."},403);if(g==="owner"&&(!Ti(String(d.password??""),de.passwordHash)||_.membership.roleTemplate!=="owner"))return S({ok:!1,error:"Owner invitations require an owner to re-enter their password."},401);try{let L=a.store.createInvitation({organizationId:a.organization.id,email:String(d.email??""),roleTemplate:g,scope:T,invitedByActorId:_.actor.id,expiresInMs:Number(d.expiresInMs)||void 0}),K=`${N.origin}/accept-invitation?token=${encodeURIComponent(L.token)}`,B=await Sa(o,{to:L.invitation.email,subject:"Your ts-cloud organization invitation",text:`Accept your ts-cloud invitation: ${K}
|
|
494
|
+
|
|
495
|
+
This link expires ${L.invitation.expiresAt} and can be used once.`});return S({invitation:L.invitation,token:L.token,acceptUrl:K,delivered:B},201)}catch(L){return S({ok:!1,error:L instanceof Error?L.message:"Invitation could not be created."},422)}}if(N.pathname==="/api/organization/invitations"&&I.method==="DELETE"){let d=await oe(I),g=Me(de);try{return S({invitation:a.store.revokeInvitation(String(d.id??""),g.actor?.id)})}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Invitation could not be revoked."},409)}}if(N.pathname==="/api/organization/invitations/resend"&&I.method==="POST"){let d=await oe(I),g=Me(de);try{let T=a.store.reissueInvitation(String(d.id??""),g.actor?.id),_=`${N.origin}/accept-invitation?token=${encodeURIComponent(T.token)}`,L=await Sa(o,{to:T.invitation.email,subject:"Your ts-cloud organization invitation",text:`Accept your ts-cloud invitation: ${_}
|
|
496
|
+
|
|
497
|
+
This replacement link expires ${T.invitation.expiresAt} and can be used once.`});return S({invitation:T.invitation,token:T.token,acceptUrl:_,delivered:L})}catch(T){return S({ok:!1,error:T instanceof Error?T.message:"Invitation could not be resent."},409)}}if(N.pathname==="/api/organization/memberships"&&I.method==="PATCH"){let d=await oe(I),g=a.store.getMembership(String(d.id??"")),T=wd(d.roleTemplate),_=Ua(d);if(!g||g.organizationId!==a.organization.id)return S({ok:!1,error:"Membership was not found."},404);if(!T||!_)return S({ok:!1,error:"Choose a valid role template and resource scope."},422);let L=Me(de);if((g.roleTemplate==="owner"||T==="owner")&&(!Ti(String(d.password??""),de.passwordHash)||L.membership?.roleTemplate!=="owner"))return S({ok:!1,error:"Ownership changes require an owner to re-enter their password."},401);let B=a.store.resolveAuthorizationTarget(a.organization.id,_)??a.store.resolveAuthorizationTarget(a.organization.id,{type:"project",id:a.project.id}),Q=a.store.listGrants(g.id),fe=Zr({membership:g,grants:Q,target:B}),ue={...g,roleTemplate:T,scope:_},He=Zr({membership:ue,grants:Q,target:B}),be={gained:He.filter((Le)=>!fe.includes(Le)),lost:fe.filter((Le)=>!He.includes(Le))};if(d.preview===!0)return S({membership:g,proposed:{roleTemplate:T,scope:_},accessDiff:be});if(String(d.confirm??"")!==g.id)return S({ok:!1,error:`Confirm this change with membership ID ${g.id}.`,accessDiff:be},409);try{return S({membership:a.store.updateMembership({id:g.id,roleTemplate:T,scope:_,actorId:L.actor?.id}),accessDiff:be})}catch(Le){return S({ok:!1,error:Le instanceof Error?Le.message:"Membership could not be updated."},409)}}if(N.pathname==="/api/organization/memberships"&&I.method==="DELETE"){let d=await oe(I),g=a.store.getMembership(String(d.id??""));if(!g||g.organizationId!==a.organization.id)return S({ok:!1,error:"Membership was not found."},404);if(String(d.confirm??"")!==g.id)return S({ok:!1,error:`Confirm removal with membership ID ${g.id}.`},409);let T=Me(de);if(g.roleTemplate==="owner"&&(T.membership?.roleTemplate!=="owner"||!Ti(String(d.password??""),de.passwordHash)))return S({ok:!1,error:"Removing an owner requires an owner to re-enter their current password."},401);try{return S({membership:a.store.revokeMembership(g.id,T.actor?.id)})}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:"Membership could not be removed."},409)}}if(N.pathname==="/api/organization/grants"&&I.method==="POST"){let d=await oe(I),g=String(d.capability??""),T=d.effect==="deny"?"deny":d.effect==="allow"?"allow":void 0,_=Ua(d),L=Me(de);if(!T||!_||!ie.includes(g))return S({ok:!1,error:"Choose a valid capability, effect, and resource scope."},422);try{return S({grant:a.store.upsertGrant({organizationId:a.organization.id,membershipId:String(d.membershipId??""),effect:T,capability:g,scope:_,actorId:L.actor?.id})},201)}catch(K){return S({ok:!1,error:K instanceof Error?K.message:"Grant could not be created."},422)}}if(N.pathname==="/api/organization/grants"&&I.method==="DELETE"){let d=await oe(I),g=Me(de),T=a.store.getGrant(String(d.id??""));if(!T||T.organizationId!==a.organization.id)return S({ok:!1,error:"Grant was not found."},404);return S({ok:a.store.removeGrant(T.id,g.actor?.id)})}if(N.pathname==="/api/tags"&&I.method==="GET")return S({tags:a.store.listTags(a.project.id),assignments:a.store.listResourceTags(a.project.id)});if(N.pathname==="/api/tags"&&I.method==="POST"){let d=await oe(I),g=a.store.upsertTag(a.project.id,String(d.name??""),String(d.color??"#5a8be0"));if(d.resourceId)a.store.assignTag(String(d.resourceId),g.id);return S({tag:g},201)}if(N.pathname==="/api/tags"&&I.method==="DELETE"){let d=await oe(I);return a.store.removeTag(String(d.resourceId??""),String(d.tagId??"")),S({ok:!0})}if(N.pathname==="/"&&!ab(N.pathname,si))return new Response(null,{status:302,headers:{location:`/server/sites?env=${encodeURIComponent(ye)}`}});if(N.pathname==="/"&&Mt?.mode==="serverless")return new Response(null,{status:302,headers:{location:`/serverless?env=${encodeURIComponent(ye)}`}});let Ka=uy(N.pathname);if(Ka)return new Response(null,{status:308,headers:{location:`${Ka}?env=${encodeURIComponent(ye)}`}});if(N.pathname==="/api/env"&&I.method==="POST"){let d=await oe(I),g=String(d.env??"");if(!m.includes(g))return S({ok:!1,error:`Unknown environment '${g}'.`,environments:m},404);return S({ok:!0,environment:g,environments:m,href:`?env=${encodeURIComponent(g)}`})}if(N.pathname==="/api/config"){let d={...oA(o),environment:ye,environments:m};return S(py(d,si))}if(N.pathname==="/api/ssh-keys"&&I.method==="GET")return S({configPath:k,keys:$t(ca(o))});if(N.pathname==="/api/ssh-keys"&&I.method==="POST"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=await Fi(k,"utf8"),T=ca(o),_=_a({configText:g,name:String(d.name??""),publicKey:String(d.publicKey??""),existingKeys:T});return await ys(k,_),nb(o,[...T,{name:String(d.name??"").trim(),publicKey:String(d.publicKey??"").trim().replace(/\s+/g," ")}]),S({ok:!0,configPath:k,keys:$t(ca(o))})}if(N.pathname==="/api/ssh-keys"&&I.method==="DELETE"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=String(d.name??N.searchParams.get("name")??""),T=await Fi(k,"utf8"),_=ca(o),L=$a({configText:T,name:g,existingKeys:_});return await ys(k,L),nb(o,_.filter((K)=>K.name!==g.trim())),S({ok:!0,configPath:k,keys:$t(ca(o))})}if(N.pathname==="/api/firewall"&&I.method==="GET")return S({configPath:k,alwaysOpen:[22,80,443],ports:rp(o)});if(N.pathname==="/api/firewall"&&I.method==="POST"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=Number(d.port);if(!ja(g))return S({ok:!1,error:"Port must be an integer between 1 and 65535."},422);let T=rp(o),_=await Fi(k,"utf8");try{await ys(k,Sy(_,g,T))}catch(B){return S({ok:!1,error:B?.message??String(B)},422)}let L=hs([...T,g]);ib(o,L);let K=d.apply===!1?null:await Xt(o,ye,`ufw allow ${g}/tcp`).catch((B)=>({ok:!1,error:String(B?.message??B)}));return S({ok:!0,configPath:k,ports:L,apply:K})}if(N.pathname==="/api/firewall"&&I.method==="DELETE"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=Number(d.port??N.searchParams.get("port"));if(!ja(g))return S({ok:!1,error:"Port must be an integer between 1 and 65535."},422);let T=rp(o),_=await Fi(k,"utf8");await ys(k,vy(_,g,T));let L=hs(T.filter((B)=>B!==g));ib(o,L);let K=d.apply===!1?null:await Xt(o,ye,`ufw delete allow ${g}/tcp`).catch((B)=>({ok:!1,error:String(B?.message??B)}));return S({ok:!0,configPath:k,ports:L,apply:K})}if(N.pathname==="/api/sites"&&I.method==="POST"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=String(d.name??"").trim(),T=String(d.root??"").trim();if(!g||!T)return S({ok:!1,error:"Site name and root are required."},422);let _={deploy:d.deploy==="bucket"?"bucket":"server",root:T,path:String(d.path??"").trim()||void 0,domain:String(d.domain??"").trim()||void 0,build:String(d.build??"").trim()||void 0,start:String(d.start??"").trim()||void 0,port:d.port?Number(d.port):void 0,type:String(d.type??"").trim()||void 0};if(_.port!==void 0&&(!Number.isInteger(_.port)||_.port<1||_.port>65535))return S({ok:!1,error:"Port must be a number between 1 and 65535."},422);let L=await Fi(k,"utf8"),K=dn({configText:L,name:g,root:_.root,domain:_.domain,path:_.path,deploy:_.deploy,build:_.build,start:_.start,port:_.port,type:_.type});return await ys(k,K),YT(o,g,Object.fromEntries(Object.entries(_).filter(([,B])=>B!==void 0))),Mt=await bs(o,ye),q.set(ye,Mt),S({ok:!0,configPath:k,site:g,data:Mt})}if(N.pathname==="/api/sites"&&I.method==="DELETE"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=String(d.name??N.searchParams.get("name")??"").trim();if(!g||!o.sites?.[g])return S({ok:!1,error:`Site '${g}' was not found.`},404);let T=await Fi(k,"utf8");return await ys(k,My({configText:T,name:g})),delete o.sites[g],Mt=await bs(o,ye),q.set(ye,Mt),S({ok:!0,configPath:k,site:g,data:Mt})}if(N.pathname==="/api/sites"&&I.method==="PATCH"){if(!k)return S({ok:!1,error:"No cloud config file was found in this checkout."},404);let d=await oe(I),g=String(d.name??"").trim(),T=o.sites?.[g];if(!g||!T)return S({ok:!1,error:`Site '${g}' was not found.`},404);if(si.role==="member"){let K=fy(d);if(!K.ok)return S({ok:!1,error:K.error},403);let B=hy({siteName:g,body:d,sites:o.sites??{},ownSites:Object.keys(si.sites)});if(!B.ok)return S({ok:!1,error:B.error},409)}if(d.port!==void 0&&d.port!==null&&d.port!==""&&(!Number.isInteger(Number(d.port))||Number(d.port)<1||Number(d.port)>65535))return S({ok:!1,error:"Port must be a number between 1 and 65535."},422);if(typeof d.domain==="string"&&d.domain.trim()&&!Zl(d.domain.trim()))return S({ok:!1,error:`Domain '${d.domain.trim()}' is not a valid hostname.`},422);let _=await Fi(k,"utf8"),L=(K,B)=>{_=Ly({configText:_,siteName:g,key:K,valueText:B})};if(d.ssl!==void 0)L("ssl",By(d.ssl)),T.ssl=d.ssl;if(d.env!==void 0&&d.env&&typeof d.env==="object")L("env",Fy(d.env)),T.env=d.env;if(d.aliases!==void 0&&Array.isArray(d.aliases)){let K=d.aliases.map((B)=>String(B));L("aliases",Uy(K)),T.aliases=K.map((B)=>B.trim().toLowerCase()).filter(Boolean)}if(d.redirects!==void 0&&d.redirects&&typeof d.redirects==="object")L("redirects",zy(d.redirects)),T.redirects=d.redirects;for(let K of["domain","path","build","start","type","root","php"])if(typeof d[K]==="string"&&d[K].trim())L(K,jy(String(d[K]).trim())),T[K]=String(d[K]).trim();if(d.port!==void 0&&d.port!==null&&d.port!=="")L("port",String(Number(d.port))),T.port=Number(d.port);return await ys(k,_),Mt=await bs(o,ye),q.set(ye,Mt),S({ok:!0,configPath:k,site:g,data:Mt})}if(N.pathname==="/api/sites/deploy"&&I.method==="POST"){let d=await oe(I),g=String(d.name??"").trim();if(!g||!o.sites?.[g])return S({ok:!1,error:`Site '${g}' was not found.`},404);if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to deploy this site.`},409);let T=ae(a,String(ye));await new ps(ct).run(new Oa,{...T,artifactRoot:t}),od(ct,T,Mt??{});let _=Yt(ct,{scope:T,desiredConfigHash:a.project.desiredConfigHash});if(_.decision.outcome==="block")return S({ok:!1,error:`Deployment blocked by security policy: ${_.decision.explanation}`,securityReview:_},409);let L={id:`deploy:${g}`,label:`Deploy ${g}`,description:`Deploy the ${g} site for ${ye}.`,command:["deploy","--env",ye,"--site",g,"--yes"],mutates:!0},K=await ao({controlPlane:a,environment:ye,actor:de,kind:"dashboard.site.deploy",resourceSlug:g,input:{site:g},execute:()=>np(L,{cwd:t,cliEntry:i})});return S({...K.result,controlPlaneOperation:K.operation,securityReview:_})}if(N.pathname==="/api/actions")return S(gb(ye));if(N.pathname==="/api/server/operations")return S(kr(o,Mt));if(N.pathname==="/api/runtime/workloads"&&I.method==="GET"){let d=await Si(o,ye);return S(d)}if(N.pathname==="/api/runtime/logs"&&I.method==="GET"){let d=String(N.searchParams.get("workload")??"");if(!d)return S({ok:!1,error:"A workload query parameter is required."},422);let g=Math.min(1000,Math.max(1,Number(N.searchParams.get("limit"))||200));try{return S(await new ge(o,ye).logs(d,{limit:g}))}catch(T){return S({ok:!1,error:String(T?.message??T)},404)}}if(N.pathname==="/api/runtime/log-sessions"&&I.method==="POST"){let d=await oe(I),g=String(d.workloadId??"");if(!g)return S({ok:!1,error:"A workloadId is required."},422);let T=await Si(o,ye),_=T.workloads.find((B)=>B.id===g);if(!_)return S({ok:!1,error:"Workload was not found in the current project and environment."},404);if(!_.capabilities.logs.supported)return S({ok:!1,error:_.capabilities.logs.reason??"Logs are unsupported for this workload."},409);let L=new ge(o,ye,{inventory:async()=>T}),K=ar.create("logs",g);return(async()=>{let B=new Date(Date.now()-Math.min(3600000,Math.max(1000,Number(d.sinceMs)||60000)));try{for(let Q=0;Q<200&&!ar.signal(K.id)?.aborted;Q++){let fe=await L.logs(g,{limit:Math.min(500,Math.max(1,Number(d.limit)||200)),since:B});for(let ue of fe.lines)if(ar.append(K.id,`${ue.timestamp?`${ue.timestamp} `:""}${ue.message}
|
|
498
|
+
`),ue.timestamp)B=new Date(Math.max(B.getTime(),new Date(ue.timestamp).getTime()+1));await Bun.sleep(3000)}if(!ar.signal(K.id)?.aborted)ar.close(K.id,"complete")}catch(Q){ar.append(K.id,Q instanceof Error?Q.message:String(Q),"stderr"),ar.close(K.id,"failed",Q instanceof Error?Q.message:String(Q))}})(),S({ok:!0,session:K,streamUrl:`/api/runtime/log-stream?id=${encodeURIComponent(K.id)}&workload=${encodeURIComponent(g)}`},201)}if((N.pathname==="/api/runtime/log-stream"||N.pathname==="/api/runtime/exec-stream")&&I.method==="GET"){let d=String(N.searchParams.get("id")??""),g=String(N.searchParams.get("workload")??""),T=Number(I.headers.get("last-event-id")??N.searchParams.get("after")??0)||0,_=ar.read(d,g,T),L=N.pathname.includes("exec")?"exec":"logs";if(!_||_.kind!==L)return S({ok:!1,error:"Runtime stream was not found in this workload scope."},404);return zT(ar,_,T,I.signal)}if((N.pathname==="/api/runtime/log-sessions"||N.pathname==="/api/runtime/exec-sessions")&&I.method==="DELETE"){let d=await oe(I),g=ar.cancel(String(d.id??""),String(d.workloadId??""));if(!g)return S({ok:!1,error:"Runtime stream was not found in this workload scope."},404);return S({ok:!0,session:g})}if(N.pathname==="/api/runtime/exec-sessions"&&I.method==="POST"){let d=await oe(I),g=String(d.workloadId??""),T=await Si(o,ye),_=T.workloads.find((Q)=>Q.id===g);if(!_)return S({ok:!1,error:"Workload was not found in the current project and environment."},404);let L=Bt.resolveSession(I),K=new ge(o,ye,{inventory:async()=>T}),B=ar.create("exec",g);return ao({controlPlane:a,environment:ye,actor:de,kind:"runtime.exec",resourceSlug:_.links.service,input:{workloadId:g,provider:_.provider,preset:d.preset?String(d.preset):null,freeForm:!!String(d.command??"").trim()},execute:()=>K.exec({workloadId:g,preset:["process","sockets","filesystem"].includes(String(d.preset))?String(d.preset):void 0,command:typeof d.command==="string"?d.command:void 0,confirm:String(d.confirm??""),recentAuth:!ke||!!L&&ve.isRecentlyAuthenticated(L)})}).then(({result:Q,operation:fe})=>{if(ar.append(B.id,`operation ${fe.id}
|
|
499
|
+
`,"system"),Q.stdout)ar.append(B.id,Q.stdout,"stdout");if(Q.stderr)ar.append(B.id,Q.stderr,"stderr");ar.close(B.id,Q.ok?"complete":"failed",Q.error)}).catch((Q)=>{let fe=Q instanceof Error?Q.message:String(Q);ar.append(B.id,fe,"stderr"),ar.close(B.id,"failed",fe)}),S({ok:!0,session:B,streamUrl:`/api/runtime/exec-stream?id=${encodeURIComponent(B.id)}&workload=${encodeURIComponent(g)}`},202)}if(N.pathname==="/api/runtime/files/read"&&I.method==="POST"){let d=await oe(I),g=await Si(o,ye),T=Bt.resolveSession(I),_=await new ge(o,ye,{inventory:async()=>g}).readFile({workloadId:String(d.workloadId??""),path:String(d.path??""),confirm:String(d.confirm??""),recentAuth:!ke||!!T&&ve.isRecentlyAuthenticated(T)});return S(_,_.ok?200:409)}if(N.pathname==="/api/runtime/files/write"&&I.method==="POST"){let d=await oe(I),g=await Si(o,ye),T=String(d.workloadId??""),_=g.workloads.find((Q)=>Q.id===T);if(!_)return S({ok:!1,error:"Workload was not found in the current project and environment."},404);let L=Bt.resolveSession(I),K=new ge(o,ye,{inventory:async()=>g}),B=await ao({controlPlane:a,environment:ye,actor:de,kind:"runtime.file.write",resourceSlug:_.links.service,input:{workloadId:T,provider:_.provider,path:String(d.path??""),bytes:Buffer.from(String(d.contentBase64??""),"base64").byteLength},execute:()=>K.writeFile({workloadId:T,path:String(d.path??""),contentBase64:String(d.contentBase64??""),confirm:String(d.confirm??""),recentAuth:!ke||!!L&&ve.isRecentlyAuthenticated(L)})});return S({...B.result,controlPlaneOperation:B.operation},B.result.ok?200:409)}if(N.pathname==="/api/runtime/operations"&&I.method==="POST"){let d=await oe(I),g=String(d.workloadId??""),T=String(d.action??"");if(!g||!["start","stop","restart","redeploy","scale","inspect"].includes(T))return S({ok:!1,error:"A valid workloadId and lifecycle action are required."},422);let _=await Si(o,ye),L=_.workloads.find((fe)=>fe.id===g);if(!L)return S({ok:!1,error:"Workload was not found in the current project and environment."},404);let K=Bt.resolveSession(I),B=new ge(o,ye,{inventory:async()=>_}),Q=await ao({controlPlane:a,environment:ye,actor:de,kind:`runtime.${T}`,resourceSlug:L.links.service,input:{workloadId:g,provider:L.provider,action:T,replicas:d.replicas==null?null:Number(d.replicas)},execute:()=>B.run({workloadId:g,action:T,replicas:d.replicas==null?void 0:Number(d.replicas),confirm:String(d.confirm??""),recentAuth:!ke||!!K&&ve.isRecentlyAuthenticated(K)})});return S({...Q.result,controlPlaneOperation:Q.operation},Q.result.ok?200:409)}if(N.pathname.startsWith("/api/protection")){let d=de.role==="admin"||Ga(de,"security:read"),g=de.role==="admin"||Ga(de,"security:manage");if(!d)return S({ok:!1,error:"Protection controls require security:read."},403);let{ProtectionControlStore:T,describePosture:_}=await import("./chunk-ymbwekjm.js"),L=new T(a.store),K=()=>{if(!g)throw Error("Changing protection controls requires security:manage.")};if(N.pathname==="/api/protection"&&I.method==="GET"){let B=L.current();return S({ok:!0,posture:_(B),controls:B,raw:L.raw()})}if(N.pathname==="/api/protection/attack-mode"&&I.method==="POST"){K();let B=await oe(I);if(B.enabled===!1)return S({ok:!0,disabled:L.disableAttackMode()});return S({ok:!0,control:L.enableAttackMode({hours:B.hours==null?void 0:Number(B.hours),reason:String(B.reason??"Enabled from the dashboard."),actorId:Me(de).actor?.id})})}if(N.pathname==="/api/protection/pause"&&I.method==="POST"){K();let B=await oe(I);if(B.enabled===!1)return S({ok:!0,resumed:L.resumeMitigations()});return S({ok:!0,control:L.pauseMitigations({hours:B.hours==null?void 0:Number(B.hours),reason:String(B.reason??""),actorId:Me(de).actor?.id})})}if(N.pathname==="/api/protection/ip-rules"&&I.method==="GET")return S({ok:!0,ipRules:L.current().ipRules});if(N.pathname==="/api/protection/ip-rules"&&(I.method==="POST"||I.method==="DELETE")){K();let B=await oe(I),Q=B.list==="allow"?"allow":"block",fe=I.method==="POST"?L.addIpRule(Q,String(B.cidr??"")):L.removeIpRule(Q,String(B.cidr??""));return S({ok:!0,ipRules:fe})}return S({ok:!1,error:"Protection endpoint was not found."},404)}if(N.pathname.startsWith("/api/spend/")||N.pathname==="/api/usage"){let d=await bb(),{store:g,service:T,gate:_}=d,L=de.role==="admin"||Ga(de,"billing:read"),K=de.role==="admin"||Ga(de,"billing:manage");if(!L)return S({ok:!1,error:"Spend data requires the billing:read capability."},403);let B=a.environments.get(ye),Q={organizationId:a.organization.id,projectId:a.project.id,environmentId:B?.id},fe=()=>{if(!K)throw Error("Changing a budget requires the billing:manage capability.")};if(N.pathname==="/api/usage"&&I.method==="GET")return S({ok:!0,...T.usageReport({organizationId:Q.organizationId,projectId:Q.projectId,period:N.searchParams.get("period")??"monthly",timezone:N.searchParams.get("timezone")??void 0})});if(N.pathname==="/api/spend/budgets"&&I.method==="GET")return S({ok:!0,budgets:g.listBudgets({organizationId:Q.organizationId,projectId:Q.projectId}).map((ue)=>({...ue,status:T.status(ue)}))});if(N.pathname==="/api/spend/budgets"&&I.method==="POST"){fe();let ue=await oe(I),He=String(ue.scope??"project"),be=g.createBudget({organizationId:Q.organizationId,projectId:He==="organization"?void 0:Q.projectId,environmentId:He==="environment"?Q.environmentId:void 0,name:String(ue.name??"").trim(),period:ue.period??"monthly",timezone:ue.timezone?String(ue.timezone):void 0,softLimitCents:ue.softLimitCents==null?void 0:Math.round(Number(ue.softLimitCents)),hardLimitCents:ue.hardLimitCents==null?void 0:Math.round(Number(ue.hardLimitCents)),graceSeconds:ue.graceSeconds==null?void 0:Number(ue.graceSeconds),dryRun:ue.dryRun!==!1});return S({ok:!0,budget:be})}if(N.pathname==="/api/spend/budgets"&&I.method==="PATCH"){fe();let ue=await oe(I),He=String(ue.id??""),be=g.getBudget(He);if(!be||be.organizationId!==Q.organizationId)return S({ok:!1,error:"Budget was not found."},404);return S({ok:!0,budget:g.updateBudget(He,{softLimitCents:ue.softLimitCents==null?be.softLimitCents:Math.round(Number(ue.softLimitCents)),hardLimitCents:ue.hardLimitCents==null?be.hardLimitCents:Math.round(Number(ue.hardLimitCents)),enabled:ue.enabled==null?be.enabled:ue.enabled===!0,dryRun:ue.dryRun==null?be.dryRun:ue.dryRun===!0},ue.expectedVersion==null?void 0:Number(ue.expectedVersion))})}if(N.pathname==="/api/spend/budgets"&&I.method==="DELETE"){fe();let ue=await oe(I),He=String(ue.id??""),be=g.getBudget(He);if(!be||be.organizationId!==Q.organizationId)return S({ok:!1,error:"Budget was not found."},404);let Le=_.closeBudget(He);return g.deleteBudget(He),S({ok:!0,deleted:!0,lifted:Le})}if(N.pathname==="/api/spend/check"&&I.method==="POST"){fe();let ue=await oe(I),{SpendRunner:He}=await import("./chunk-jh1593zx.js"),be=new He({controlPlane:a.store,store:g,alerts:Ge});if(ue.apply!==!0){let Se=g.budgetsForScope(Q.organizationId,Q.projectId,Q.environmentId);return S({ok:!0,applied:!1,preview:Se.map((Ee)=>T.status(Ee))})}let Le=await be.run({...Q,environmentKind:B?.kind});return S({ok:!0,applied:!0,result:Le})}if(N.pathname==="/api/spend/enforcement"&&I.method==="GET")return S({ok:!0,enforcement:_.listUnder({organizationId:Q.organizationId})});if(N.pathname==="/api/spend/release"&&I.method==="POST"){fe();let ue=await oe(I),He=_.close(String(ue.budgetId??""),ue.action);return S({ok:He,released:He,note:He?"The next spend cycle re-applies this if spend is still over the threshold.":"That action was not in force."})}if(N.pathname==="/api/spend/anomalies"&&I.method==="GET")return S({ok:!0,anomalies:g.listAnomalies({organizationId:Q.organizationId,projectId:Q.projectId,unacknowledgedOnly:N.searchParams.get("unacknowledged")==="true"})});if(N.pathname==="/api/spend/anomalies/acknowledge"&&I.method==="POST"){fe();let ue=await oe(I);return S({ok:!0,acknowledged:g.acknowledgeAnomaly(String(ue.id??""))})}return S({ok:!1,error:"Spend endpoint was not found."},404)}if(N.pathname.startsWith("/api/health/")||N.pathname.startsWith("/api/alerts")||N.pathname.startsWith("/api/notifications/")){let d=a.environments.get(ye),g=a.store.listResources(a.project.id,d?.id),T=de.role==="admin"||!!d&&pa(de,d.id,"runtime:read")?g:g.filter((B)=>Ar(de,B.id,"runtime:read")),_=(B)=>!B||T.some((Q)=>Q.id===B),L=(B)=>{if(!B)return;let Q=g.find((fe)=>fe.id===B||fe.slug===B);if(!Q)throw Error("Alert resource was not found.");if(!_(Q.id))throw Error("Alert resource is outside your authorized scope.");return Q.id},K=Me(de).actor;if(N.pathname==="/api/health/checks"&&I.method==="GET")return S({ok:!0,checks:Ge.listHealthChecks(a.project.id,d?.id).filter((B)=>_(B.resourceId)).map((B)=>({...B,results:Ge.listHealthResults(B.id,20)}))});if(N.pathname==="/api/health/checks"&&I.method==="POST"){let B=await oe(I),Q=String(B.kind??"http");if(Q==="command"&&de.role!=="admin")return S({ok:!1,error:"Command health checks require an administrator."},403);let fe={method:String(B.config?.method??"GET").toUpperCase().slice(0,10),path:B.config?.path?String(B.config.path).slice(0,500):void 0,port:B.config?.port==null?void 0:Number(B.config.port),command:Array.isArray(B.config?.command)?B.config.command.map(String).slice(0,20):void 0,expectedStatuses:Array.isArray(B.config?.expectedStatuses)?B.config.expectedStatuses.map(Number).filter(Number.isInteger).slice(0,20):void 0,expectedBody:B.config?.expectedBody?String(B.config.expectedBody).slice(0,500):void 0};return S({ok:!0,check:Ge.createHealthCheck({projectId:a.project.id,environmentId:d?.id,resourceId:L(B.resourceId??B.resource),name:String(B.name??""),kind:Q,target:String(B.target??""),config:fe,intervalSeconds:Number(B.intervalSeconds)||60,timeoutSeconds:Number(B.timeoutSeconds)||10,failureThreshold:Number(B.failureThreshold)||3,recoveryThreshold:Number(B.recoveryThreshold)||2,regions:Array.isArray(B.regions)?B.regions.map(String):["local"],enabled:B.enabled!==!1})},201)}if(N.pathname==="/api/health/checks"&&I.method==="PATCH"){let B=await oe(I),Q=Ge.getHealthCheck(String(B.id??""));if(!Q||!_(Q.resourceId))return S({ok:!1,error:"Health check was not found."},404);return S({ok:!0,check:Ge.setHealthCheckEnabled(Q.id,B.enabled!==!1)})}if(N.pathname==="/api/health/checks/test"&&I.method==="POST"){let B=await oe(I),Q=Ge.getHealthCheck(String(B.id??""));if(!Q||!_(Q.resourceId))return S({ok:!1,error:"Health check was not found."},404);return S({ok:!0,productionIncidentCreated:!1,result:await new Oe(Ge).probe(Q)})}if(N.pathname==="/api/health/checks/run"&&I.method==="POST"){let B=await oe(I),Q=Ge.getHealthCheck(String(B.id??""));if(!Q||!_(Q.resourceId))return S({ok:!1,error:"Health check was not found."},404);let fe=await new Oe(Ge).runAndEvaluate(Q),ue=[];for(let He of fe.evaluations.filter((be)=>be.notify&&be.alert)){let be=oi.enqueue(a.organization.id,He.alert,He.transition);ue.push(...await oi.deliverAll(be))}return S({ok:!0,...fe,deliveries:ue})}if(N.pathname==="/api/alerts/rules"&&I.method==="GET")return S({ok:!0,rules:Ge.listRules(a.project.id,d?.id).filter((B)=>_(B.resourceId))});if(N.pathname==="/api/alerts/rules"&&I.method==="POST"){let B=await oe(I),Q=B.healthCheckId?Ge.getHealthCheck(String(B.healthCheckId)):void 0;if(B.healthCheckId&&(!Q||!_(Q.resourceId)))return S({ok:!1,error:"Health check was not found."},404);return S({ok:!0,rule:Ge.createRule({projectId:a.project.id,environmentId:d?.id,resourceId:L(B.resourceId??B.resource)??Q?.resourceId,healthCheckId:Q?.id,name:String(B.name??""),signal:String(B.signal??(Q?"health":"")),operator:String(B.operator??(Q?"unhealthy":"gt")),threshold:B.threshold==null?void 0:Number(B.threshold),recoveryThreshold:B.recoveryThreshold==null?void 0:Number(B.recoveryThreshold),windowMs:Number(B.windowMs)||300000,consecutive:Number(B.consecutive)||Q?.failureThreshold||3,recoveryConsecutive:Number(B.recoveryConsecutive)||Q?.recoveryThreshold||2,noDataPolicy:["ignore","pending","firing"].includes(String(B.noDataPolicy))?B.noDataPolicy:"pending",severity:["info","warning","critical"].includes(String(B.severity))?B.severity:"warning",groupBy:Array.isArray(B.groupBy)?B.groupBy.map(String):[],labels:B.labels&&typeof B.labels==="object"?B.labels:{},enabled:B.enabled!==!1})},201)}if(N.pathname==="/api/alerts/rules"&&I.method==="PATCH"){let B=await oe(I),Q=Ge.getRule(String(B.id??""));if(!Q||!_(Q.resourceId))return S({ok:!1,error:"Alert rule was not found."},404);return S({ok:!0,rule:Ge.setRuleEnabled(Q.id,B.enabled!==!1)})}if(N.pathname==="/api/alerts/evaluate"&&I.method==="POST")return S({ok:!0,...await pp(d?.id)});if(N.pathname==="/api/alerts"&&I.method==="GET")return S({ok:!0,alerts:Ge.listAlerts(a.project.id,{environmentId:d?.id,states:N.searchParams.getAll("state").length?N.searchParams.getAll("state"):void 0,limit:Number(N.searchParams.get("limit"))||200}).filter((B)=>_(B.resourceId)).map((B)=>({...B,deliveries:Ge.listDeliveries({alertId:B.id,limit:50})}))});if(N.pathname==="/api/alerts/action"&&I.method==="POST"){let B=await oe(I),Q=Ge.getAlert(String(B.id??""));if(!Q||!_(Q.resourceId))return S({ok:!1,error:"Alert was not found."},404);let fe=String(B.action??"");if(fe==="acknowledge")return S({ok:!0,alert:Ge.acknowledge(Q.id,K?.id??"")});if(fe==="assign")return S({ok:!0,alert:Ge.assign(Q.id,B.ownerActorId==="me"?K?.id:B.ownerActorId?String(B.ownerActorId):void 0,K?.id)});if(fe==="silence"){if(de.role!=="admin")return S({ok:!1,error:"Silencing production alerts requires an administrator."},403);let ue=Bt.resolveSession(I);if(ke&&(!ue||!ve.isRecentlyAuthenticated(ue)))return S({ok:!1,error:"Recent authentication is required to silence alerts.",stepUpRequired:!0},401);return S({ok:!0,alert:Ge.silenceAlert(Q.id,String(B.until??""),K?.id)})}return S({ok:!1,error:"Action must be acknowledge, assign, or silence."},422)}if(N.pathname==="/api/alerts/silences"&&I.method==="POST"){let B=await oe(I);return S({ok:!0,id:Ge.createSilence({projectId:a.project.id,environmentId:d?.id,resourceId:L(B.resourceId??B.resource),matcher:B.matcher,reason:String(B.reason??""),startsAt:String(B.startsAt??new Date().toISOString()),endsAt:String(B.endsAt??""),timezone:String(B.timezone??"UTC"),actorId:K?.id})},201)}if(N.pathname==="/api/notifications/channels"&&I.method==="GET")return S({ok:!0,channels:Ge.listChannels(a.organization.id)});if(N.pathname==="/api/notifications/channels"&&I.method==="POST"){let B=await oe(I),Q=String(B.kind??""),fe=Q==="email"?{to:B.config?.to,from:B.config?.from}:Q==="telegram"?{chatId:String(B.config?.chatId??"")}:{};return S({ok:!0,channel:Ge.createChannel({organizationId:a.organization.id,name:String(B.name??""),kind:Q,config:fe,credential:B.credential?String(B.credential):void 0,actorId:K?.id})},201)}if(N.pathname==="/api/notifications/channels"&&I.method==="PATCH"){let B=await oe(I),Q=String(B.id??"");if(B.credential)return S({ok:!0,channel:Ge.rotateChannel(Q,String(B.credential))});let fe=String(B.status??"paused");if(!["active","paused","disabled"].includes(fe))return S({ok:!1,error:"Channel status must be active, paused, or disabled."},422);return S({ok:!0,channel:Ge.setChannelStatus(Q,fe)})}if(N.pathname==="/api/notifications/channels/test"&&I.method==="POST"){let B=await oe(I);return S({ok:!0,productionIncidentCreated:!1,result:await oi.testChannel(String(B.id??""))})}if(N.pathname==="/api/notifications/routes"&&I.method==="GET")return S({ok:!0,routes:Ge.listRoutes(a.organization.id)});if(N.pathname==="/api/notifications/routes"&&I.method==="POST"){let B=await oe(I),Q=Array.isArray(B.channelIds)?B.channelIds.map(String):[];if(Q.some((fe)=>Ge.getChannel(fe)?.organizationId!==a.organization.id))return S({ok:!1,error:"Route contains an unavailable channel."},422);return S({ok:!0,route:Ge.createRoute({organizationId:a.organization.id,name:String(B.name??""),priority:Number(B.priority)||0,matcher:B.matcher&&typeof B.matcher==="object"?B.matcher:{},channelIds:Q,quietHours:B.quietHours,groupWaitSeconds:Number(B.groupWaitSeconds)||30,reminderSeconds:B.reminderSeconds==null?void 0:Number(B.reminderSeconds),escalation:Array.isArray(B.escalation)?B.escalation:[],template:B.template?String(B.template):void 0,rateLimitPerMinute:Number(B.rateLimitPerMinute)||60,enabled:B.enabled!==!1})},201)}if(N.pathname==="/api/notifications/routes"&&I.method==="PATCH"){let B=await oe(I),Q=Ge.getRoute(String(B.id??""));if(!Q||Q.organizationId!==a.organization.id)return S({ok:!1,error:"Notification route was not found."},404);return S({ok:!0,route:Ge.setRouteEnabled(Q.id,B.enabled!==!1)})}if(N.pathname==="/api/notifications/routes/preview"&&I.method==="POST"){let B=await oe(I),fe=(B.alertId?Ge.getAlert(String(B.alertId)):void 0)??{id:"preview",ruleId:"preview",projectId:a.project.id,environmentId:d?.id,resourceId:L(B.resourceId??B.resource),dedupKey:"preview",groupKey:String(B.groupKey??"default"),state:"firing",severity:["info","warning","critical"].includes(String(B.severity))?B.severity:"warning",title:String(B.title??"Rule preview"),evidence:{},failureCount:1,recoveryCount:0,occurrenceCount:1,firstSeenAt:new Date().toISOString(),lastSeenAt:new Date().toISOString(),firingAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return S({ok:!0,productionIncidentCreated:!1,matches:oi.preview(a.organization.id,fe,String(B.eventType??"firing")).map((ue)=>({route:ue.route,channels:ue.channels,quiet:ue.quiet}))})}if(N.pathname==="/api/notifications/deliveries"&&I.method==="GET")return S({ok:!0,deliveries:Ge.listDeliveries({alertId:N.searchParams.get("alertId")??void 0,states:N.searchParams.getAll("state"),limit:Number(N.searchParams.get("limit"))||200})});if(N.pathname==="/api/notifications/deliveries/retry"&&I.method==="POST"){let B=await oe(I),Q=Ge.getDelivery(String(B.id??""));if(!Q)return S({ok:!1,error:"Delivery was not found."},404);return Ge.updateDelivery(Q.id,{state:"retrying",attempt:Math.max(0,Q.attempt-1),nextAttemptAt:new Date().toISOString()}),S({ok:!0,delivery:await oi.deliver(Q.id)})}}if(N.pathname.startsWith("/api/jobs")||N.pathname.startsWith("/api/workers")){let d=a.environments.get(ye),g=a.store.listResources(a.project.id,d?.id),_=de.role==="admin"||!!d&&pa(de,d.id,"automation:read")?g:g.filter((Se)=>Ar(de,Se.id,"automation:read")),L=(Se)=>!Se||_.some((Ee)=>Ee.id===Se),K=Me(de).actor,B=q.get(ye)??O,Q=kr(o,B),fe=Q.filter((Se)=>!Se.danger&&["scheduler","backup","worker"].includes(Se.group)),ue=V(o),He=()=>{let Se=Bt.resolveSession(I);return!ke||!!Se&&ve.isRecentlyAuthenticated(Se)},be=(Se)=>{if(!Se||typeof Se!=="object"||Array.isArray(Se))return{};let Ee=Object.entries(Se).slice(0,50);if(Ee.some(([,it])=>typeof it!=="string"||!/^(?:secret|ssm|arn|env):\/\//.test(it)))throw Error("Job payload values must be secret or environment references, never inline values.");return Object.fromEntries(Ee)},Le=(Se,Ee,it)=>a.store.appendEvent({organizationId:a.organization.id,projectId:a.project.id,resourceId:it,actorId:K?.id,type:`job.${Se}`,payload:Ee});if(N.pathname==="/api/jobs/preview"&&I.method==="POST"){let Se=await oe(I);try{return S({ok:!0,productionExecutionCreated:!1,preview:rt(String(Se.expression??""),String(Se.timezone??"UTC"),new Date(Se.from?String(Se.from):Date.now()),Number(Se.count)||5)})}catch(Ee){return S({ok:!1,error:Ee instanceof Error?Ee.message:"Schedule preview could not be generated.",productionExecutionCreated:!1},422)}}if(N.pathname==="/api/jobs"&&I.method==="GET")return S({ok:!0,jobs:Er.list(a.project.id,{environmentId:d?.id}).filter((Se)=>L(Se.resourceId)).map((Se)=>({...Se,preview:rt(Se.normalizedExpression,Se.timezone,new Date,5),capability:$n(Se),lastExecution:Er.listExecutions(Se.id,1)[0]}))});if(N.pathname==="/api/jobs"&&I.method==="POST"){let Se=await oe(I),Ee=String(Se.provider??(ue==="serverless"?"eventbridge":"server")),it=ue==="serverless"?"eventbridge":"server";if(Ee!==it)return S({ok:!1,error:`${ue} environments accept ${it} schedules through this adapter.`},422);let lt=Se.operationId?String(Se.operationId):void 0;if(Ee==="server"&&(!lt||!fe.some((dr)=>dr.id===lt)))return S({ok:!1,error:"Server jobs require an allowlisted operation target."},422);let yt=$n({provider:Ee,expression:String(Se.expression??""),flexibleMinutes:Number(Se.flexibleMinutes)||0,missedRunPolicy:Se.missedRunPolicy==="catch_up"?"catch_up":"skip",overlapPolicy:["allow","forbid","replace"].includes(String(Se.overlapPolicy))?Se.overlapPolicy:"forbid"});if(!yt.supported)return S({ok:!1,error:yt.notes.join(" ")},422);let Qn=Se.resourceId?g.find((dr)=>dr.id===Se.resourceId||dr.slug===Se.resourceId):void 0;if(Se.resourceId&&(!Qn||!L(Qn.id)))return S({ok:!1,error:"Job resource was not found."},404);try{let dr=Ee==="server"?{kind:"dashboard_operation",operationId:lt}:{kind:"serverless_scheduler",action:"run"},bo=Er.create({organizationId:a.organization.id,projectId:a.project.id,environmentId:d?.id,resourceId:Qn?.id,name:String(Se.name??""),provider:Ee,expression:String(Se.expression??""),timezone:String(Se.timezone??"UTC"),startsAt:Se.startsAt?String(Se.startsAt):void 0,endsAt:Se.endsAt?String(Se.endsAt):void 0,flexibleMinutes:Number(Se.flexibleMinutes)||0,target:dr,payloadRefs:be(Se.payloadRefs),missedRunPolicy:Se.missedRunPolicy==="catch_up"?"catch_up":"skip",overlapPolicy:["allow","forbid","replace"].includes(String(Se.overlapPolicy))?Se.overlapPolicy:"forbid",retryPolicy:{maxAttempts:Number(Se.maxAttempts)||3,backoffSeconds:Number(Se.backoffSeconds)||30,deadLetterRef:Se.deadLetterRef?String(Se.deadLetterRef):void 0},timeoutSeconds:Number(Se.timeoutSeconds)||900,enabled:Se.enabled!==!1,origin:"managed",ownerActorId:K?.id,observedState:{},reconciliationStatus:"pending"});return Le("created",{jobId:bo.id,provider:bo.provider,expression:bo.normalizedExpression},bo.resourceId),S({ok:!0,job:bo,capability:yt},201)}catch(dr){return S({ok:!1,error:dr instanceof Error?dr.message:"Scheduled job could not be created."},422)}}if(N.pathname==="/api/jobs"&&I.method==="PATCH"){let Se=await oe(I),Ee=Er.get(String(Se.id??""));if(!Ee||!L(Ee.resourceId))return S({ok:!1,error:"Scheduled job was not found."},404);if(Ee.origin==="config")return S({ok:!1,error:"Config-defined schedules must be edited in cloud.config.ts and reconciled."},409);let it=Se.missedRunPolicy==null?void 0:String(Se.missedRunPolicy),lt=Se.overlapPolicy==null?void 0:String(Se.overlapPolicy);if(it&&!["skip","catch_up"].includes(it))return S({ok:!1,error:"Missed-run policy must be skip or catch_up."},422);if(lt&&!["allow","forbid","replace"].includes(lt))return S({ok:!1,error:"Overlap policy must be allow, forbid, or replace."},422);try{let yt=Er.updateSchedule(Ee.id,{expression:Se.expression?String(Se.expression):void 0,timezone:Se.timezone?String(Se.timezone):void 0,missedRunPolicy:it,overlapPolicy:lt,timeoutSeconds:Se.timeoutSeconds==null?void 0:Number(Se.timeoutSeconds)});return Le("updated",{jobId:yt.id,expression:yt.normalizedExpression,version:yt.version},yt.resourceId),S({ok:!0,job:yt})}catch(yt){return S({ok:!1,error:yt instanceof Error?yt.message:"Scheduled job could not be updated."},422)}}if(N.pathname==="/api/jobs/action"&&I.method==="POST"){let Se=await oe(I),Ee=Er.get(String(Se.id??""));if(!Ee||!L(Ee.resourceId))return S({ok:!1,error:"Scheduled job was not found."},404);let it=String(Se.action??"");if(it==="run"){let lt=lp.enqueue(Ee,{trigger:"manual",actorId:K?.id});return Le("run_queued",{jobId:Ee.id,executionId:lt.id},Ee.resourceId),S({ok:!0,execution:lt},202)}if(["disable","delete"].includes(it)&&d?.kind==="production"){if(String(Se.confirm??"")!==it)return S({ok:!1,error:`Type "${it}" to confirm this production change.`},409);if(!He())return S({ok:!1,error:"Recent authentication is required for this production change.",stepUpRequired:!0},401)}if(it==="enable"||it==="disable"){let lt=Er.setEnabled(Ee.id,it==="enable");return Le(it==="enable"?"enabled":"disabled",{jobId:Ee.id},Ee.resourceId),S({ok:!0,job:lt})}if(it==="delete")try{return Er.remove(Ee.id),Le("deleted",{jobId:Ee.id,name:Ee.name},Ee.resourceId),S({ok:!0,deleted:Ee.id})}catch(lt){return S({ok:!1,error:lt instanceof Error?lt.message:"Scheduled job could not be deleted."},409)}return S({ok:!1,error:"Action must be run, enable, disable, or delete."},422)}if(N.pathname==="/api/jobs/history"&&I.method==="GET"){let Se=Er.get(String(N.searchParams.get("jobId")??""));if(!Se||!L(Se.resourceId))return S({ok:!1,error:"Scheduled job was not found."},404);return S({ok:!0,executions:Er.listExecutions(Se.id,Number(N.searchParams.get("limit"))||100).map((Ee)=>({...Ee,logs:Ee.operationId?kt.logs(Ee.operationId,{limit:500}):[]}))})}if(N.pathname==="/api/jobs/reconcile"&&I.method==="POST"){if(!d)return S({ok:!1,error:"Environment was not found."},404);let Se=$r(Er,o,{organization:a.organization,project:a.project,environment:d,resources:g});return Le("reconciled",Se),S({ok:!0,reconciliation:Se})}if(N.pathname==="/api/workers"&&I.method==="GET"){let Se=Array.isArray(B.workersDetail??B.workers)?B.workersDetail??B.workers:[];return S({ok:!0,workers:Er.listWorkers(a.project.id,d?.id).filter((Ee)=>L(Ee.resourceId)).map((Ee)=>{let it=Se.find((lt)=>lt.name===Ee.name||lt.site===Ee.target.site);return it?{...Ee,observedState:{...Ee.observedState,status:it.status??"configured",currentJob:it.currentJob??null,failures:Number(it.failed??it.failures)||0,processed:Number(it.processed)||0}}:Ee})})}if(N.pathname==="/api/workers/action"&&I.method==="POST"){let Se=await oe(I),Ee=Er.getWorker(String(Se.id??""));if(!Ee||!L(Ee.resourceId))return S({ok:!1,error:"Worker was not found."},404);let it=String(Se.action??"");if(it==="restart"){if(String(Se.confirm??"")!==Ee.name)return S({ok:!1,error:`Type "${Ee.name}" to restart this worker.`},409);let lt=Q.find((dr)=>dr.id===Ee.target.operationId);if(!lt)return S({ok:!1,error:"The allowlisted worker restart operation is unavailable."},409);let yt=await Dr(o,ye,lt),Qn=Er.reconcileWorker(Ee.id,yt.ok?"in_sync":"unavailable",{...Ee.observedState,lastRestartAt:new Date().toISOString(),command:yt.command??null,error:yt.error??yt.stderr??null});return Le("worker_restarted",{workerId:Ee.id,ok:yt.ok},Ee.resourceId),S({...yt,worker:Qn},yt.ok?200:409)}if(it==="scale")return S({ok:!1,error:Ee.provider==="systemd"?"Systemd worker scale is config-managed; edit the worker definition and reconcile.":"This provider does not expose safe worker scaling through the current adapter."},422);return S({ok:!1,error:"Action must be restart or scale."},422)}}if(N.pathname.startsWith("/api/telemetry/")){let d=a.environments.get(ye),g=new Ve(a.store),T=a.store.listResources(a.project.id,d?.id),_=["/api/telemetry/query","/api/telemetry/tail","/api/telemetry/export","/api/telemetry/saved-queries","/api/telemetry/refresh"].includes(N.pathname)?"runtime:logs":"runtime:read",L=de.role==="admin"||!!d&&pa(de,d.id,_),K=L?T:T.filter((be)=>Ar(de,be.id,_)),B=(be)=>Jy(K,L,be),Q=(be)=>{let Le=new Date,Se={"1h":3600000,"6h":21600000,"24h":86400000,"7d":604800000,"30d":2592000000},Ee=String(be.to??Le.toISOString()),it=String(be.from??new Date(new Date(Ee).getTime()-(Se[String(be.range??"1h")]??Se["1h"])).toISOString()),lt=(Qn)=>{let dr=(Array.isArray(Qn)?Qn:String(Qn??"").split(",")).map(String).filter(Boolean);return dr.length?dr:void 0},yt=lt(be.kinds)?.filter((Qn)=>["metric","log","trace","request","event"].includes(Qn));return{projectId:a.project.id,environmentId:d?.id,resourceIds:B(be.resources),kinds:yt,names:lt(be.names),sources:lt(be.sources),levels:lt(be.levels),from:it,to:Ee,text:String(be.text??"")||void 0,traceId:String(be.traceId??"")||void 0,requestId:String(be.requestId??"")||void 0,deploymentId:String(be.deploymentId??"")||void 0,releaseId:String(be.releaseId??"")||void 0,workloadId:String(be.workloadId??"")||void 0,cursor:String(be.cursor??"")||void 0,limit:Number(be.limit)||void 0}},fe=Object.fromEntries(N.searchParams.entries()),ue=(be=!1)=>Un({controlPlane:a.store,projectId:a.project.id,environmentId:d?.id,config:o,environment:ye,force:be,lightweight:!be}),He=()=>{let be=a.store.getSetting(`telemetry.collection:${a.project.id}:${d?.id??"all"}`)??{};return{generatedAt:String(be.generatedAt??new Date().toISOString()),cached:!0,statuses:Array.isArray(be.statuses)?be.statuses:[],errors:Array.isArray(be.errors)?be.errors:[],policy:be.policy??je(a.store,a.project.id)}};if(N.pathname==="/api/telemetry/status"&&I.method==="GET"){ue(!1);let be=He(),Le=L?be.statuses:g.status(a.project.id,d?.id,be.policy.rawDays,be.policy.samplingRate,K.map((Ee)=>Ee.id)),Se=Le.reduce((Ee,it)=>Ee+it.estimatedDailyBytes*30,0);return S({ok:!0,generatedAt:be.generatedAt,cached:be.cached,sources:Le,errors:L?be.errors:[],policy:be.policy,retention:{rawDays:be.policy.rawDays,downsampleAfterDays:be.policy.downsampleAfterDays,downsampleBucketMs:be.policy.downsampleBucketMs,maxRecords:be.policy.maxRecords},estimatedMonthlyBytes:Se,estimatedMonthlyCostUsd:qn(Se,be.policy),costEstimateConfigured:be.policy.estimatedStorageUsdPerGbMonth>0})}if(N.pathname==="/api/telemetry/settings"&&I.method==="GET")return S({ok:!0,policy:je(a.store,a.project.id)});if(N.pathname==="/api/telemetry/settings"&&I.method==="PATCH"){let be=zn(a.store,a.project.id,await oe(I));return Xy(a.project.id),S({ok:!0,policy:be})}if(N.pathname==="/api/telemetry/query"&&I.method==="GET"){ue(!1);let be=He();return S({ok:!0,collection:{generatedAt:be.generatedAt,cached:be.cached},...g.query(Q(fe))})}if(N.pathname==="/api/telemetry/tail"&&I.method==="GET"){ue(!1);let be=new TextEncoder,Le=new Date,Se=Q({...fe,kinds:fe.kinds||"log,request,event,trace",from:fe.from||new Date(Le.getTime()-120000).toISOString(),to:Le.toISOString(),limit:Math.min(1000,Number(fe.limit)||200),cursor:void 0}),Ee=I.headers.get("last-event-id")||String(fe.cursor??"")||void 0,it,lt=!1,yt=!1,Qn=new ReadableStream({start(dr){let bo=()=>{if(lt)return;if(lt=!0,it)clearInterval(it);I.signal.removeEventListener("abort",bo);try{dr.close()}catch{}},Ep=async()=>{if(lt||yt)return;yt=!0;try{let zo=g.tail({...Se,to:new Date(Date.now()+1000).toISOString()},Ee);for(let Tp of zo.records)Ee=Ii(Tp)??Ee,dr.enqueue(be.encode(`id: ${Ee??""}
|
|
500
|
+
event: record
|
|
501
|
+
data: ${JSON.stringify(Tp)}
|
|
502
|
+
|
|
503
|
+
`));if(zo.cursor)Ee=zo.cursor}catch(zo){dr.enqueue(be.encode(`event: error
|
|
504
|
+
data: ${JSON.stringify({message:zo instanceof Error?zo.message:String(zo)})}
|
|
505
|
+
|
|
506
|
+
`))}finally{yt=!1}};Ep(),it=setInterval(()=>{if(Ep(),!lt)dr.enqueue(be.encode(`event: heartbeat
|
|
507
|
+
data: ${JSON.stringify({cursor:Ee,at:new Date().toISOString()})}
|
|
508
|
+
|
|
509
|
+
`))},5000),it.unref?.(),I.signal.addEventListener("abort",bo,{once:!0})},cancel(){if(lt=!0,it)clearInterval(it)}});return new Response(Qn,{headers:{"cache-control":"no-cache, no-transform",connection:"keep-alive","content-type":"text/event-stream; charset=utf-8","x-accel-buffering":"no"}})}if(N.pathname==="/api/telemetry/series"&&I.method==="GET"){ue(!1);let be=He(),Le=["sum","avg","min","max","count","p50","p90","p95","p99"].includes(String(fe.aggregation))?fe.aggregation:"avg",Se=Q({...fe,kinds:"metric",limit:5000}),Ee=g.series({...Se,bucketMs:Number(fe.bucketMs)||60000,aggregation:Le,timezone:String(fe.timezone??"UTC"),compareFrom:fe.compareFrom,compareTo:fe.compareTo});return S({ok:!0,collection:{generatedAt:be.generatedAt,cached:be.cached},query:{aggregation:Le,bucketMs:Number(fe.bucketMs)||60000,timezone:String(fe.timezone??"UTC")},series:Ee})}if(N.pathname==="/api/telemetry/refresh"&&I.method==="POST")return S({ok:!0,...await ue(!0)});if(N.pathname==="/api/telemetry/export"&&I.method==="POST"){let be=await oe(I);await ue(!1);let Le=g.query({...Q(be),limit:Math.min(5000,Number(be.limit)||5000),cursor:void 0});if((be.format==="csv"?"csv":"json")==="json")return new Response(JSON.stringify({exportedAt:new Date().toISOString(),query:Q(be),...Le},null,2),{headers:{"content-disposition":'attachment; filename="ts-cloud-telemetry.json"',"content-type":"application/json; charset=utf-8"}});let Ee=["timestamp","kind","source","name","level","value","unit","message","traceId","requestId","deploymentId","releaseId","workloadId"],it=[Ee.join(","),...Le.records.map((lt)=>Ee.map((yt)=>`"${String(lt[yt]??"").replaceAll('"','""')}"`).join(","))].join(`
|
|
510
|
+
`);return new Response(it,{headers:{"content-disposition":'attachment; filename="ts-cloud-telemetry.csv"',"content-type":"text/csv; charset=utf-8"}})}if(N.pathname==="/api/telemetry/saved-queries"&&I.method==="GET"){let be=Me(de);return S({ok:!0,queries:g.listSavedQueries(a.project.id,be.actor?.id)})}if(N.pathname==="/api/telemetry/saved-queries"&&I.method==="POST"){let be=await oe(I),Le=Me(de);return S({ok:!0,query:g.saveQuery(a.project.id,Le.actor?.id,String(be.name??""),Q(be.query??be))},201)}if(N.pathname==="/api/telemetry/saved-queries"&&I.method==="DELETE"){let be=await oe(I),Le=Me(de),Se=g.deleteSavedQuery(a.project.id,Le.actor?.id,String(be.id??""));return S({ok:Se},Se?200:404)}}if(N.pathname.startsWith("/api/configuration")){let d=a.environments.get(ye),g=de.role==="admin"||!!si.capabilities?.includes("secrets:read"),T=de.role==="admin"||!!si.capabilities?.includes("secrets:write"),_={projectId:a.project.id,environmentId:d?.id},L={"cache-control":"no-store"};if(N.pathname==="/api/configuration"&&I.method==="GET"){let K=Object.fromEntries(N.searchParams),B=K.scopeType||K.scopeId?sa(K,_):void 0,Q=["variable","secret"].includes(String(K.kind))?K.kind:void 0,fe=B?.type==="preview"?nr.previews.getInstance(B.id):void 0,ue=fe?nr.previews.getDefinition(fe.definitionId):void 0,He=B?await Wn.resolve({projectId:a.project.id,environmentId:B.environmentId,resourceId:B.resourceId,functionId:B.type==="function"?B.id:void 0,previewId:B.previewId,trustedPreview:!!fe&&!fe.fork,allowedPreviewSecrets:ue?.inheritedSecrets,nativeReferences:!0,canReadSecretMetadata:g}):void 0,be=a.store.listResources(a.project.id);return S({ok:!0,entries:Wn.list({projectId:a.project.id,scope:B,kind:Q,search:K.search,canReadSecretMetadata:g}),effectiveEntries:He?Object.values(He.entries).filter((Le)=>!Q||Le.kind===Q).filter((Le)=>!K.search||Le.key.toLowerCase().includes(String(K.search).toLowerCase())):[],configurationHash:He?.configurationHash,warnings:He?.warnings??[],scopes:{project:a.project,environments:a.store.listEnvironments(a.project.id),resources:be.filter((Le)=>Le.kind!=="function"),functions:be.filter((Le)=>Le.kind==="function"),previews:nr.previews.listInstances({projectId:a.project.id}).filter((Le)=>Le.status!=="destroyed").map((Le)=>({id:Le.id,name:Le.name,environmentId:Le.baseEnvironmentId,resourceId:Le.resourceId,fork:Le.fork,status:Le.status}))}},200,L)}if(N.pathname==="/api/configuration/export"&&I.method==="GET"){let K=sa(Object.fromEntries(N.searchParams),_);return new Response(Wn.exportVariables({projectId:a.project.id,scope:K}),{headers:{...L,"content-disposition":'attachment; filename="ts-cloud.env"',"content-type":"text/plain; charset=utf-8"}})}if(N.pathname==="/api/configuration/plan"&&I.method==="POST"){let K=await oe(I),B=sa(K,_),Q=K.values&&typeof K.values==="object"&&!Array.isArray(K.values)?Object.fromEntries(Object.entries(K.values).map(([fe,ue])=>[fe,String(ue)])):{};return S({ok:!0,plan:Wn.plan({projectId:a.project.id,scope:B,values:Q,removeMissing:K.removeMissing===!0})},200,L)}if(N.pathname==="/api/configuration"&&I.method==="POST"){let K=await oe(I),B=sa(K,_),Q=K.kind==="secret"?"secret":"variable",fe=String(K.key??"");if(Q==="secret"&&!T)return S({ok:!1,error:"Secret write permission is required."},403,L);try{let ue=await Wn.set({organizationId:a.organization.id,projectId:a.project.id,scope:B,key:fe,kind:Q,value:K.value==null?void 0:String(K.value),reference:K.reference==null?void 0:String(K.reference),backend:K.backend,required:K.required===!0,expectedVersion:K.expectedVersion==null?void 0:Number(K.expectedVersion),confirmed:String(K.confirm??"")===fe,idempotencyKey:I.headers.get("idempotency-key")??K.idempotencyKey,actorId:Me(de).actor?.id});return S({ok:!0,entry:Wn.list({projectId:a.project.id,scope:B,canReadSecretMetadata:g}).find((He)=>He.id===ue.entry.id),mutation:ue.mutation,warnings:ue.warnings},ue.mutation.added.length?201:200,L)}catch(ue){return S({ok:!1,error:ue instanceof Error?ue.message:String(ue)},409,L)}}if(N.pathname==="/api/configuration/import"&&I.method==="POST"){let K=await oe(I),B=sa(K,_),Q=Array.isArray(K.secretKeys)?K.secretKeys.map(String):[];if(Q.length&&!T)return S({ok:!1,error:"Secret write permission is required."},403,L);try{let fe=await Wn.importDotenv({organizationId:a.organization.id,projectId:a.project.id,scope:B,source:String(K.source??""),secretKeys:Q,backend:K.backend,confirmed:K.confirm==="import",idempotencyKey:I.headers.get("idempotency-key")??K.idempotencyKey,actorId:Me(de).actor?.id});return S({ok:fe.document.valid,diagnostics:fe.document.diagnostics,mutation:fe.mutation,warnings:fe.warnings},fe.document.valid?200:422,L)}catch(fe){return S({ok:!1,error:fe instanceof Error?fe.message:String(fe)},409,L)}}if(N.pathname==="/api/configuration/dependencies"&&I.method==="POST"){let K=await oe(I),B=go.get(String(K.entryId??"")),Q=a.store.getResource(String(K.resourceId??""));if(!B||B.projectId!==a.project.id||!Q||Q.projectId!==a.project.id)return S({ok:!1,error:"Configuration entry or dependent resource was not found."},404,L);return S({ok:!0,dependency:go.setDependency({entryId:B.id,resourceId:Q.id,injectionTarget:["native_reference","file"].includes(String(K.injectionTarget))?K.injectionTarget:"environment",required:K.required!==!1,requiresRedeploy:K.requiresRedeploy!==!1,lastDeployedVersion:K.lastDeployedVersion==null?void 0:Number(K.lastDeployedVersion)})},200,L)}if(N.pathname==="/api/configuration/transfer"&&I.method==="POST"){let K=await oe(I),B=go.get(String(K.id??"")),Q=sa({...K,scopeType:K.targetScopeType,scopeId:K.targetScopeId},_);if(!B||B.projectId!==a.project.id)return S({ok:!1,error:"Configuration entry was not found."},404,L);if(B.kind==="secret"&&!T)return S({ok:!1,error:"Secret write permission is required."},403,L);try{let fe=await Wn.transfer({entryId:B.id,targetScope:Q,mode:K.mode==="move"?"move":"copy",confirmed:K.confirm===B.key,actorId:Me(de).actor?.id,idempotencyKey:I.headers.get("idempotency-key")??K.idempotencyKey});return S({ok:!0,entry:Wn.list({projectId:a.project.id,scope:Q,canReadSecretMetadata:g}).find((ue)=>ue.id===fe.entry.id),mutation:fe.mutation},200,L)}catch(fe){return S({ok:!1,error:fe instanceof Error?fe.message:String(fe)},409,L)}}if(N.pathname==="/api/configuration/bulk"&&I.method==="POST"){let K=await oe(I),B=Array.isArray(K.ids)?K.ids.map(String).slice(0,500):[],Q=B.map((ue)=>go.get(ue)).filter((ue)=>!!ue&&ue.projectId===a.project.id);if(Q.length!==B.length)return S({ok:!1,error:"One or more configuration entries were not found."},404,L);if(Q.some((ue)=>ue.kind==="secret")&&!T)return S({ok:!1,error:"Secret write permission is required."},403,L);if(K.action!=="delete"||K.confirm!=="bulk")return S({ok:!1,error:"Bulk deletion requires action delete and confirm bulk."},409,L);let fe=[];try{for(let ue of Q)fe.push(await Wn.remove({entryId:ue.id,expectedVersion:ue.version,confirmed:!0,actorId:Me(de).actor?.id}));return S({ok:!0,removed:fe.flatMap((ue)=>ue.removed),affectedResourceIds:[...new Set(fe.flatMap((ue)=>ue.affectedResourceIds))].sort()},200,L)}catch(ue){return S({ok:!1,error:ue instanceof Error?ue.message:String(ue),partial:fe.flatMap((He)=>He.removed)},409,L)}}if(N.pathname==="/api/configuration/reveal"&&I.method==="POST"){let K=await oe(I),B=Bt.resolveSession(I);try{return S({ok:!0,value:await Wn.reveal({entryId:String(K.id??""),canRevealSecrets:g,recentlyAuthenticated:!ke||!!B&&ve.isRecentlyAuthenticated(B),actorId:Me(de).actor?.id})},200,L)}catch(Q){return S({ok:!1,error:Q instanceof Error?Q.message:String(Q)},403,L)}}if(N.pathname==="/api/configuration"&&I.method==="DELETE"){let K=await oe(I),B=go.get(String(K.id??""));if(B?.kind==="secret"&&!T)return S({ok:!1,error:"Secret write permission is required."},403,L);if(!B||B.projectId!==a.project.id)return S({ok:!1,error:"Configuration entry was not found."},404,L);try{return S({ok:!0,mutation:await Wn.remove({entryId:B.id,expectedVersion:Number(K.expectedVersion),confirmed:String(K.confirm??"")===B.key,actorId:Me(de).actor?.id})},200,L)}catch(Q){return S({ok:!1,error:Q instanceof Error?Q.message:String(Q)},409,L)}}}if(N.pathname.startsWith("/api/fleet")){let d=Me(de).actor?.id,g=(T,_=409)=>S({ok:!1,error:T instanceof Error?T.message:String(T)},_,{"cache-control":"no-store"});if(N.pathname==="/api/fleet"&&I.method==="GET")return S({ok:!0,servers:ua.list(a.project.id),resources:a.store.listResources(a.project.id),operations:kt.list({projectId:a.project.id,limit:200}).filter((T)=>T.operation.kind.startsWith("fleet."))},200,{"cache-control":"no-store"});if(N.pathname==="/api/fleet"&&I.method==="POST"){let T=await oe(I);try{return S({ok:!0,server:Oi.enroll({organizationId:a.organization.id,projectId:a.project.id,name:String(T.name??""),provider:["aws","hetzner"].includes(String(T.provider))?T.provider:"ssh",providerId:T.providerId?String(T.providerId):void 0,region:T.region?String(T.region):void 0,zone:T.zone?String(T.zone):void 0,endpoint:String(T.endpoint??""),sshUser:String(T.sshUser??"deploy"),sshPort:T.sshPort?Number(T.sshPort):22,credentialRef:String(T.credentialRef??""),roles:Array.isArray(T.roles)?T.roles:[],labels:T.labels&&typeof T.labels==="object"?T.labels:{}})},201)}catch(_){return g(_,422)}}if(N.pathname==="/api/fleet/action"&&I.method==="POST"){let T=await oe(I),_=String(T.id??""),L=String(T.action??"");try{if(L==="test")return S({ok:!0,server:await Oi.test(_)});if(L==="validate")return S({ok:!0,server:await Oi.validate(_)});if(L==="review_host_key")return S({ok:!0,server:Oi.reviewHostKey(_,String(T.fingerprint??""))});if(L==="bootstrap")return S({ok:!0,...Oi.bootstrap(_,T.confirmed===!0)},T.confirmed===!0?202:200);if(L==="heartbeat")return S({ok:!0,server:Oi.heartbeat(_,{usage:T.usage&&typeof T.usage==="object"?T.usage:{}})});if(L==="drain")return S({ok:!0,server:Oi.drain(_,T.completed===!0)});if(L==="uncordon")return S({ok:!0,server:Oi.uncordon(_)});if(L==="archive")return S({ok:!0,server:Oi.archive(_,String(T.confirmation??""))});return g("Unsupported fleet action.",422)}catch(K){return g(K)}}}if(N.pathname.startsWith("/api/capacity")){let d=(g,T=409)=>S({ok:!1,error:g instanceof Error?g.message:String(g)},T,{"cache-control":"no-store"});if(N.pathname==="/api/capacity"&&I.method==="GET")return S({ok:!0,pools:fo.listPools(a.project.id),placements:fo.listPlacements(a.project.id),servers:ua.list(a.project.id)},200,{"cache-control":"no-store"});if(N.pathname==="/api/capacity"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,pool:fo.createPool({organizationId:a.organization.id,projectId:a.project.id,name:String(g.name??""),purpose:String(g.purpose??"application"),backend:String(g.backend??"server"),region:g.region?String(g.region):void 0,architecture:g.architecture?String(g.architecture):void 0,labels:g.labels&&typeof g.labels==="object"?g.labels:{},requiredServerLabels:g.requiredServerLabels&&typeof g.requiredServerLabels==="object"?g.requiredServerLabels:{},toleratedTaints:Array.isArray(g.toleratedTaints)?g.toleratedTaints.map(String):[],capacity:g.capacity&&typeof g.capacity==="object"?g.capacity:{},maxWorkloads:Number(g.maxWorkloads??10),costWeight:Number(g.costWeight??1),spreadKey:g.spreadKey?String(g.spreadKey):void 0,concurrency:Number(g.concurrency??1),ephemeralWorkspaces:!0,allowProductionSecrets:!1,status:"active"})},201)}catch(T){return d(T,422)}}if(N.pathname==="/api/capacity/member"&&I.method==="POST"){let g=await oe(I);try{return fo.addMember(String(g.poolId??""),String(g.serverId??"")),S({ok:!0,pool:fo.getPool(String(g.poolId??""))})}catch(T){return d(T,422)}}if(N.pathname==="/api/capacity/explain"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,decisions:cp.explain(a.project.id,{purpose:String(g.purpose??"application"),resources:g.resources&&typeof g.resources==="object"?g.resources:{},region:g.region?String(g.region):void 0,architecture:g.architecture?String(g.architecture):void 0,labels:g.labels&&typeof g.labels==="object"?g.labels:{}})})}catch(T){return d(T,422)}}if(N.pathname==="/api/capacity/action"&&I.method==="POST"){let g=await oe(I);try{if(g.action==="drain")return S({ok:!0,...cp.drainPool(String(g.poolId??""))});if(g.action==="enable")return S({ok:!0,pool:fo.updatePool(String(g.poolId??""),{status:"active"})});if(g.action==="disable")return S({ok:!0,pool:fo.updatePool(String(g.poolId??""),{status:"disabled"})});return d("Unsupported capacity action.",422)}catch(T){return d(T,422)}}}if(N.pathname.startsWith("/api/regions")){let d=(g,T=409)=>S({ok:!1,error:g instanceof Error?g.message:String(g)},T,{"cache-control":"no-store"});if(N.pathname==="/api/regions"&&I.method==="GET")return S({ok:!0,topologies:Fo.list(a.project.id).map((g)=>({topology:g,targets:Fo.targets(g.id),channels:Fo.channels(g.id),route:Fo.route(g.id),executions:Fo.executions(g.id)}))},200,{"cache-control":"no-store"});if(N.pathname==="/api/regions"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,topology:dp.create({organizationId:a.organization.id,projectId:a.project.id,environmentId:a.environments.get(ye)?.id,name:String(g.name??""),hostname:String(g.hostname??""),regions:Array.isArray(g.regions)?g.regions:[],trafficPolicy:g.trafficPolicy==="weighted"||g.trafficPolicy==="latency"?g.trafficPolicy:"active_passive",dataPolicy:{replicate:Array.isArray(g.replicate)?g.replicate:["s3","dynamodb","secrets"],maxLagSeconds:Number(g.maxLagSeconds??30),retainOnDestroy:g.retainOnDestroy!==!1},dnsProvider:"route53",cdnEnabled:g.cdnEnabled===!0,wafEnabled:g.wafEnabled===!0})},201)}catch(T){return d(T,422)}}if(N.pathname==="/api/regions/action"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,...dp.enqueue({topologyId:String(g.topologyId??""),kind:String(g.action??""),targetRegion:g.targetRegion?String(g.targetRegion):void 0,revision:g.revision?String(g.revision):void 0,manifest:g.manifest&&typeof g.manifest==="object"?g.manifest:{},confirmation:g.confirmation?String(g.confirmation):void 0,deleteData:g.deleteData===!0})},202)}catch(T){return d(T,422)}}}if(N.pathname.startsWith("/api/maintenance")){let d=(g,T=409)=>S({ok:!1,error:g instanceof Error?g.message:String(g)},T,{"cache-control":"no-store"});if(N.pathname==="/api/maintenance"&&I.method==="GET")return S({ok:!0,manifests:qi.manifests(a.organization.id),windows:qi.windows(a.project.id),campaigns:qi.campaigns(a.project.id).map((g)=>({campaign:g,targets:qi.targets(g.id)})),cleanups:qi.cleanups(a.project.id),drills:qi.drills(a.project.id)},200,{"cache-control":"no-store"});if(N.pathname==="/api/maintenance/cleanup-preview"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,plan:await Rd.previewCleanup({projectId:a.project.id,kind:String(g.kind??"operations"),criteria:{olderThanDays:Number(g.olderThanDays??30)}},up)},201)}catch(T){return d(T,422)}}if(N.pathname==="/api/maintenance/cleanup-apply"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,...Rd.enqueueCleanup(String(g.planId??""),String(g.confirmation??""))},202)}catch(T){return d(T,422)}}if(N.pathname==="/api/maintenance/drill"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,drill:qi.createDrill({projectId:a.project.id,scenario:String(g.scenario??"control_plane"),isolatedTarget:String(g.isolatedTarget??""),expectedRpoMinutes:Number(g.expectedRpoMinutes??60),expectedRtoMinutes:Number(g.expectedRtoMinutes??30),recoveryPointId:g.recoveryPointId?String(g.recoveryPointId):void 0,topologyId:g.topologyId?String(g.topologyId):void 0})},201)}catch(T){return d(T,422)}}if(N.pathname==="/api/maintenance/drill-run"&&I.method==="POST"){let g=await oe(I);try{return S({ok:!0,...Rd.enqueueDrill(String(g.drillId??""))},202)}catch(T){return d(T,422)}}}if(N.pathname.startsWith("/api/volumes")){let d=a.environments.get(ye),g=Me(de).actor?.id,T=(_,L=409)=>S({ok:!1,error:_ instanceof Error?_.message:String(_)},L,{"cache-control":"no-store"});if(N.pathname==="/api/volumes"&&I.method==="GET"){let _=Ad.inventory(a.project.id,d?.id),L=a.store.listResources(a.project.id,d?.id).map((K)=>({id:K.id,name:K.name,slug:K.slug,kind:K.kind,provider:K.provider,providerId:K.providerId}));return S({ok:!0,volumes:_,resources:L,operations:kt.list({projectId:a.project.id,limit:100}).filter((K)=>K.operation.kind.startsWith("volume.")),recoveryPoints:sr.listRecoveryPoints(a.project.id).filter((K)=>K.kind==="volume"),providers:kd.map((K)=>({provider:K.provider,type:K.type,capabilities:K.capabilities()}))},200,{"cache-control":"no-store"})}if(N.pathname==="/api/volumes"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.create({organizationId:a.organization.id,projectId:a.project.id,environmentId:d?.id,resourceId:_.resourceId?String(_.resourceId):void 0,name:String(_.name??""),provider:String(_.provider??"docker"),type:_.type==="docker"?"docker":_.type,capacityBytes:_.capacityBytes==null?void 0:Number(_.capacityBytes),filesystem:_.filesystem?String(_.filesystem):void 0,encrypted:_.encrypted===!0,desiredState:_.desiredState&&typeof _.desiredState==="object"?_.desiredState:{},actorId:g})},202,{"cache-control":"no-store"})}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes/attach"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.attach(String(_.volumeId??""),{resourceId:String(_.resourceId??""),targetPath:String(_.targetPath??""),readOnly:_.readOnly===!0,uid:_.uid==null?void 0:Number(_.uid),gid:_.gid==null?void 0:Number(_.gid),mode:_.mode?String(_.mode):void 0,propagation:_.propagation,driverOptions:_.driverOptions&&typeof _.driverOptions==="object"?_.driverOptions:{},actorId:g})},202)}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes/detach"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.detach(String(_.volumeId??""),String(_.attachmentId??""),{force:_.force===!0,drained:_.drained===!0,unmounted:_.unmounted===!0,confirmation:_.confirmation?String(_.confirmation):void 0,actorId:g})},202)}catch(L){return T(L)}}if(N.pathname==="/api/volumes/resize"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.resize(String(_.volumeId??""),Number(_.capacityBytes),{drained:_.drained===!0,actorId:g})},202)}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes/snapshot"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.snapshot(String(_.volumeId??""),{name:_.name?String(_.name):void 0,actorId:g})},202)}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes/restore"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,...Vi.restore(String(_.snapshotId??""),{name:String(_.name??""),actorId:g})},202)}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes/discover"&&I.method==="POST")try{return S({ok:!0,volumes:await Vi.discover({organizationId:a.organization.id,projectId:a.project.id,environmentId:d?.id,actorId:g})})}catch(_){return T(_,502)}if(N.pathname==="/api/volumes/adopt"&&I.method==="POST"){let _=await oe(I);try{return S({ok:!0,volume:Vi.adopt(String(_.volumeId??""),{name:String(_.name??""),actorId:g})})}catch(L){return T(L,422)}}if(N.pathname==="/api/volumes"&&I.method==="DELETE"){let _=await oe(I),L=Bt.resolveSession(I);try{return S({ok:!0,...Vi.delete(String(_.volumeId??""),{recentAuthAt:!ke||L&&ve.isRecentlyAuthenticated(L)?new Date().toISOString():void 0,confirmation:_.confirmation?String(_.confirmation):void 0,backupOverride:_.backupOverride===!0,backupOverrideConfirmation:_.backupOverrideConfirmation?String(_.backupOverrideConfirmation):void 0,actorId:g})},202)}catch(K){return T(K)}}}if(N.pathname==="/api/backups"&&I.method==="GET"){let d=a.environments.get(ye),g=sr.listPolicies(a.project.id,d?.id),T=new Set(g.map((Q)=>Q.id)),_=sr.listRecoveryPoints(a.project.id).filter((Q)=>!Q.policyId||T.has(Q.policyId)),L=sr.listJobs(a.project.id).filter((Q)=>!Q.policyId||T.has(Q.policyId)),K=(Q)=>({...Q,credentialRef:void 0,encryptionKeyRef:void 0,credentialsConfigured:!!Q.credentialRef,clientEncryptionConfigured:!!Q.encryptionKeyRef}),B=await Promise.all(sr.listDestinations(a.project.id).map(async(Q)=>({...K(Q),credentialStatus:await Vg(Q,Ui)})));return S({ok:!0,destinations:B,policies:g,recoveryPoints:_,jobs:L,coverage:sr.coverage(a.project.id).filter((Q)=>T.has(Q.policy.id)),resources:d?a.store.listResources(a.project.id,d.id).map((Q)=>({id:Q.id,name:Q.name,slug:Q.slug,kind:Q.kind})):[]})}if(N.pathname==="/api/backups/destinations"&&I.method==="POST"){let d=await oe(I),g=String(d.name??"").trim(),T=String(d.provider??""),_=String(d.encryption??"provider"),L=`secret://data-services/backups/${a.project.id}/${g}`,K=[];if(!["aws_s3","s3_compatible","aws_backup"].includes(T))return S({ok:!1,error:"A supported backup destination provider is required."},422);if(!["provider","client_side","both"].includes(_))return S({ok:!1,error:"Encryption must be provider, client_side, or both."},422);try{let B,Q;if(d.credentials&&typeof d.credentials==="object"&&!Array.isArray(d.credentials))B=`${L}/credentials`,await Ui.put(B,JSON.stringify(d.credentials)),K.push(B);if(_!=="provider"){let ue=String(d.encryptionKey??"");if(ue.length<32)throw Error("Client-side encryption keys must contain at least 32 characters.");Q=`${L}/encryption-key`,await Ui.put(Q,ue),K.push(Q)}let fe=sr.createDestination({organizationId:a.organization.id,projectId:a.project.id,name:g,provider:T,endpoint:d.endpoint?String(d.endpoint):void 0,endpointPolicy:d.endpointPolicy==="allow_private"?"allow_private":"public_https",bucket:d.bucket?String(d.bucket):void 0,prefix:String(d.prefix??""),region:d.region?String(d.region):mo,forcePathStyle:d.forcePathStyle===!0,credentialRef:B,encryption:_,encryptionKeyRef:Q,immutability:d.immutability&&typeof d.immutability==="object"&&!Array.isArray(d.immutability)?d.immutability:{},status:"untested"});return S({ok:!0,destination:{...fe,credentialRef:void 0,encryptionKeyRef:void 0,credentialsConfigured:!!B,clientEncryptionConfigured:!!Q}},201)}catch(B){for(let Q of K)await Ui.remove(Q).catch(()=>{});return S({ok:!1,error:B instanceof Error?B.message:String(B)},422)}}if(N.pathname==="/api/backups/destinations/test"&&I.method==="POST"){let d=await oe(I),g=sr.getDestination(String(d.id??""));if(!g||g.projectId!==a.project.id)return S({ok:!1,error:"Backup destination was not found."},404);if(g.provider==="aws_backup")return S({ok:!1,error:"AWS Backup destinations are verified by creating a provider recovery point."},422);try{return await ap.test(g),S({ok:!0,destination:sr.recordDestinationTest(g.id,{ok:!0})})}catch(T){let _=T instanceof Error?T.message:String(T);return sr.recordDestinationTest(g.id,{ok:!1,error:_}),S({ok:!1,error:_},502)}}if(N.pathname==="/api/backups/policies"&&I.method==="POST"){let d=await oe(I),g=a.environments.get(ye),T=sr.getDestination(String(d.destinationId??"")),_=String(d.resourceKind??""),L=d.dataServiceId?String(d.dataServiceId):void 0,K=L?Ot.get(L):void 0,B=d.resourceId?String(d.resourceId):void 0,Q=B?a.store.getResource(B):void 0;if(!g)return S({ok:!1,error:"Environment was not found."},404);if(!T||T.projectId!==a.project.id)return S({ok:!1,error:"Backup destination was not found."},404);if(!["managed_database","logical_database","volume","files","control_plane","infrastructure"].includes(_))return S({ok:!1,error:"A supported backup resource kind is required."},422);if(L&&(!K||K.projectId!==a.project.id||K.environmentId!==g.id))return S({ok:!1,error:"Data service was not found in this environment."},404);if(B&&(!Q||Q.projectId!==a.project.id||Q.environmentId!==g.id))return S({ok:!1,error:"Resource was not found in this environment."},404);if(_==="managed_database"&&!K)return S({ok:!1,error:"Managed database policies require a data service."},422);if(_==="logical_database"&&(!K||!["container","server"].includes(K.provider)))return S({ok:!1,error:"Logical database policies require an on-box data service."},422);if(_==="volume"&&(!Q||!/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/.test(String(d.volumeName??""))))return S({ok:!1,error:"Volume policies require a scoped resource and valid volumeName."},422);let fe=Array.isArray(d.includePatterns)?d.includePatterns.map(String).filter(Boolean):[];if(_==="files"&&(!Q||!fe.length))return S({ok:!1,error:"File policies require a scoped resource and at least one project-relative include path."},422);if(_==="control_plane"&&T.encryption==="provider")return S({ok:!1,error:"Control-plane policies require a destination with client-side encryption."},422);if(_==="infrastructure"&&(T.provider!=="aws_backup"||!fe.some((ue)=>ue.startsWith("resource:arn:"))||!fe.some((ue)=>ue.startsWith("role:arn:"))))return S({ok:!1,error:"Infrastructure policies require an AWS Backup destination plus resource:<arn> and role:<arn> include values."},422);try{let ue=sr.createPolicy({organizationId:a.organization.id,projectId:a.project.id,environmentId:g.id,resourceId:B,dataServiceId:L,destinationId:T.id,name:String(d.name??"").trim(),resourceKind:_,schedule:String(d.schedule??"daily"),timezone:String(d.timezone??"UTC"),retention:d.retention&&typeof d.retention==="object"&&!Array.isArray(d.retention)?d.retention:{keepLast:7,expireAfterDays:30},compression:["none","gzip","zstd"].includes(String(d.compression))?d.compression:"gzip",encryption:["destination","client_side","both"].includes(String(d.encryption))?d.encryption:"destination",includePatterns:_==="volume"?[String(d.volumeName),...fe]:fe,excludePatterns:Array.isArray(d.excludePatterns)?d.excludePatterns.map(String):[],expectedRpoMinutes:Math.max(1,Number(d.expectedRpoMinutes)||1440),expectedRtoMinutes:Math.max(1,Number(d.expectedRtoMinutes)||120),healthCheckId:d.healthCheckId?String(d.healthCheckId):void 0,enabled:d.enabled!==!1});return S({ok:!0,policy:ue},201)}catch(ue){return S({ok:!1,error:ue instanceof Error?ue.message:String(ue)},422)}}if(N.pathname==="/api/backups/run"&&I.method==="POST"){let d=await oe(I),g=sr.getPolicy(String(d.policyId??"")),T=a.environments.get(ye);if(!g||g.projectId!==a.project.id||g.environmentId!==T?.id)return S({ok:!1,error:"Backup policy was not found in this environment."},404);try{let _=jo.enqueueBackup(g,new Date().toISOString(),Me(de).actor?.id);return S({ok:!0,job:_},202)}catch(_){return S({ok:!1,error:_ instanceof Error?_.message:String(_)},409)}}if(N.pathname==="/api/backups/verify"&&I.method==="POST"){let d=await oe(I),g=sr.getRecoveryPoint(String(d.recoveryPointId??""));if(!g||g.projectId!==a.project.id)return S({ok:!1,error:"Recovery point was not found."},404);return S({ok:!0,job:jo.enqueueVerification(g)},202)}if(N.pathname==="/api/backups/restore"&&I.method==="POST"){let d=await oe(I),g=sr.getRecoveryPoint(String(d.recoveryPointId??"")),T=d.mode==="in_place"?"in_place":"isolated",_=d.target&&typeof d.target==="object"&&!Array.isArray(d.target)?{...d.target,inPlace:T==="in_place"}:{inPlace:T==="in_place"},L=Bt.resolveSession(I),K={mode:T,target:_,targetName:String(d.targetName??""),confirm:d.confirm?String(d.confirm):void 0,recentAuth:!ke||!!L&&ve.isRecentlyAuthenticated(L),downtimeAcknowledged:d.downtimeAcknowledged===!0,safetyBackupId:d.safetyBackupId?String(d.safetyBackupId):void 0};if(!g||g.projectId!==a.project.id)return S({ok:!1,error:"Recovery point was not found."},404);if(d.drill===!0&&T!=="isolated")return S({ok:!1,error:"Recovery drills must use an isolated target."},422);try{let B=jo.planRestore(g,K);if(d.execute!==!0)return S({ok:!0,plan:B,executionCreated:!1});let Q=jo.enqueueRestore(g,{...K,drill:d.drill===!0,actorId:Me(de).actor?.id});return S({ok:!0,plan:B,job:Q},202)}catch(B){return S({ok:!1,error:B instanceof Error?B.message:String(B)},409)}}if(N.pathname==="/api/backups/recovery-points"&&I.method==="POST"){let d=await oe(I),g=sr.getRecoveryPoint(String(d.id??""));if(!g||g.projectId!==a.project.id)return S({ok:!1,error:"Recovery point was not found."},404);if(d.held==null&&d.pinned==null)return S({ok:!1,error:"held or pinned must be provided."},422);return S({ok:!0,recoveryPoint:sr.updateRecoveryPoint(g.id,{held:d.held==null?g.held:d.held===!0,pinned:d.pinned==null?g.pinned:d.pinned===!0})})}if(N.pathname==="/api/backups/retention"&&I.method==="POST")return S({ok:!0,jobs:jo.enqueueRetention()},202);if(N.pathname==="/api/data-services/capabilities"&&I.method==="GET"){let d=String(N.searchParams.get("engine")??""),g=String(N.searchParams.get("provider")??"");if(!["postgres","mysql","mariadb","redis","mongodb","libsql"].includes(d)||!["aws_rds","aws_aurora","aws_elasticache","server","container","external"].includes(g))return S({ok:!1,error:"A supported engine and provider are required."},422);return S({ok:!0,engine:d,provider:g,capabilities:qt(d,g)})}if(N.pathname==="/api/data-services"&&I.method==="GET"){let d=a.environments.get(ye),g=Ot.list(a.project.id,d?.id).map((T)=>{let _=Ot.credential(T.id);return{...T,credentialRef:void 0,credential:_?{configured:!0,username:_.username,version:_.version,rotatedAt:_.rotatedAt}:void 0,dependencies:Ot.dependencies(T.id).map((L)=>({resourceId:L.resourceId,requiresRedeploy:L.requiresRedeploy}))}});return S({ok:!0,services:g})}if(N.pathname==="/api/data-services/preview"&&I.method==="POST"){let d=await oe(I);if(d.id){let _=Ot.get(String(d.id)),L=a.environments.get(ye),K=String(d.action??"");if(!_||_.projectId!==a.project.id||_.environmentId!==L?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);if(!Id.includes(K))return S({ok:!1,error:`Action must be one of: ${Id.join(", ")}.`},422);try{return S({ok:!0,plan:Va.plan(_,K,d.changes??{})})}catch(B){return S({ok:!1,error:B instanceof Error?B.message:String(B)},422)}}let g=String(d.engine??""),T=String(d.provider??"");if(!["postgres","mysql","mariadb","redis","mongodb","libsql"].includes(g)||!["aws_rds","aws_aurora","aws_elasticache","server","container","external"].includes(T))return S({ok:!1,error:"A supported engine and provider are required."},422);return S({ok:!0,capabilities:qt(g,T),defaults:{publicExposure:!1,backupRetentionDays:7,deletionProtection:!0},productionExecutionCreated:!1})}if(N.pathname==="/api/data-services"&&I.method==="POST"){let d=await oe(I),g=String(d.engine??""),T=String(d.provider??""),_=a.environments.get(ye),L=Me(de);if(!_)return S({ok:!1,error:"Environment was not found."},404);if(!["postgres","mysql","mariadb","redis","mongodb","libsql"].includes(g)||!["aws_rds","aws_aurora","aws_elasticache","server","container","external"].includes(T))return S({ok:!1,error:"A supported engine and provider are required."},422);let K={organizationId:a.organization.id,projectId:a.project.id,environmentId:_.id,resourceId:d.resourceId?String(d.resourceId):void 0,name:String(d.name??"").trim(),engine:g,provider:T,placement:String(d.placement??d.name??"").trim(),engineVersion:d.engineVersion?String(d.engineVersion):void 0,plan:String(d.plan??(T==="aws_elasticache"?"cache.t4g.micro":T==="aws_aurora"?"db.serverless":"db.t4g.micro")),storageGb:d.storageGb==null?void 0:Number(d.storageGb),highAvailability:d.highAvailability===!0,publicExposure:d.publicExposure===!0,allowedCidrs:Array.isArray(d.allowedCidrs)?d.allowedCidrs.map(String):[],desiredState:d.desiredState&&typeof d.desiredState==="object"&&!Array.isArray(d.desiredState)?d.desiredState:{},observedState:{},origin:d.adopt===!0?"adopted":"managed",managementEnabled:d.adopt!==!0,ownerActorId:L.actor?.id,username:d.username?String(d.username):void 0};try{if(d.adopt===!0){let Q=Ot.create({...K,status:"adopted",credentialRef:void 0});return S({ok:!0,service:Q,readOnly:!0},201)}if(!sp({provider:T,engine:g}))return S({ok:!1,error:`No ${T}/${g} provisioning adapter is configured; adopt it read-only or choose a supported provider.`},422);let B=await Va.create(K);return S({ok:!0,service:B.service,operationId:B.operationId,oneTimeCredential:B.credential},201)}catch(B){return S({ok:!1,error:B instanceof Error?B.message:String(B)},422)}}if(N.pathname==="/api/data-services/connections"&&I.method==="GET"){let d=Ot.get(String(N.searchParams.get("id")??"")),g=a.environments.get(ye);if(!d||d.projectId!==a.project.id||d.environmentId!==g?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);let T=typeof d.observedState.endpoint==="string"?d.observedState.endpoint:void 0,_=typeof d.observedState.readerEndpoint==="string"?d.observedState.readerEndpoint:void 0,L=Number(d.observedState.port)||(d.engine==="postgres"?5432:d.engine==="redis"?6379:d.engine==="mongodb"?27017:d.engine==="libsql"?8080:3306),K=typeof d.observedState.database==="string"?d.observedState.database:void 0,B=typeof d.observedState.tls==="boolean"?d.observedState.tls:d.provider.startsWith("aws_"),Q=[...T?[{type:d.publicExposure?"external":"internal",host:T,port:L,database:K,tls:B}]:[],..._?[{type:"internal",host:_,port:L,database:K,tls:B}]:[],{type:"tunnel",host:T??d.placement,port:L,database:K,tls:B}];return S({ok:!0,serviceId:d.id,guidance:bn(d,Q)})}if(N.pathname==="/api/data-services/action"&&I.method==="POST"){let d=await oe(I),g=Ot.get(String(d.id??"")),T=a.environments.get(ye),_=String(d.action??"");if(!g||g.projectId!==a.project.id||g.environmentId!==T?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);if(!Id.includes(_))return S({ok:!1,error:`Action must be one of: ${Id.join(", ")}.`},422);let L=d.changes&&typeof d.changes==="object"&&!Array.isArray(d.changes)?d.changes:{};try{let K=Va.plan(g,_,L);if(d.execute!==!0)return S({ok:!0,plan:K,productionExecutionCreated:!1});let B=Va.enqueue(g,_,L,Me(de).actor?.id);return S({ok:!0,plan:K,operationId:B},202)}catch(K){return S({ok:!1,error:K instanceof Error?K.message:String(K)},409)}}if(N.pathname==="/api/data-services/dependencies"&&I.method==="POST"){let d=await oe(I),g=Ot.get(String(d.id??"")),T=a.environments.get(ye),_=a.store.getResource(String(d.resourceId??""));if(!g||g.projectId!==a.project.id||g.environmentId!==T?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);if(!_||_.projectId!==a.project.id||_.environmentId!==T?.id)return S({ok:!1,error:"Dependent resource was not found in this environment."},404);if(d.remove===!0)return S({ok:Ot.removeDependency(g.id,_.id)});return Ot.addDependency({serviceId:g.id,resourceId:_.id,secretRef:g.credentialRef??`secret://data-services/${g.projectId}/${g.name}`,requiresRedeploy:d.requiresRedeploy!==!1}),S({ok:!0,dependencies:Ot.dependencies(g.id).map((L)=>({resourceId:L.resourceId,requiresRedeploy:L.requiresRedeploy}))})}if(N.pathname==="/api/data-services/management"&&I.method==="POST"){let d=await oe(I),g=Ot.get(String(d.id??"")),T=a.environments.get(ye);if(!g||g.projectId!==a.project.id||g.environmentId!==T?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);if(g.origin!=="adopted"||d.reviewed!==!0||d.confirm!==g.name)return S({ok:!1,error:`Enabling management requires reviewed=true and typing ${g.name}.`},409);return S({ok:!0,service:Ot.update(g.id,g.version,{managementEnabled:!0})})}if(N.pathname==="/api/data-services/reveal"&&I.method==="POST"){let d=await oe(I),g=Ot.get(String(d.id??"")),T=a.environments.get(ye),_=g?Ot.credential(g.id):void 0;if(!g||g.projectId!==a.project.id||g.environmentId!==T?.id)return S({ok:!1,error:"Data service was not found in this environment."},404);if(!_)return S({ok:!1,error:"No managed credential is configured."},404);return S({ok:!0,credential:{username:_.username,password:await Ui.resolve(_.secretRef),version:_.version}},200,{"cache-control":"no-store"})}if(N.pathname==="/api/databases"&&I.method==="GET")return S(await Oh(o,ye));if(N.pathname==="/api/databases"&&I.method==="POST"){let d=await oe(I),g=String(d.name??"").trim();if(!uo(g))return S({ok:!1,error:"Database name must be a valid identifier (letters, numbers, underscore; not starting with a digit)."},422);return S({...await _h(o,ye,g),name:g})}if(N.pathname==="/api/databases/vitess"&&I.method==="GET"){let d=await Lh(o,ye);return S({...d,unhealthy:Bh(d.tablets),missingPrimary:jh(d)})}if(N.pathname==="/api/databases/vitess/provision"&&I.method==="POST"){let d=await oe(I);try{return S(await Gh(o,ye,{keyspace:String(d.keyspace??""),username:String(d.username??""),password:String(d.password??""),sharded:d.sharded===!0,confirm:String(d.confirm??"")}))}catch(g){return S({ok:!1,error:g instanceof Error?g.message:String(g)},422)}}if(N.pathname==="/api/databases/vitess/migrations"&&I.method==="GET"){let d=N.searchParams.get("keyspace")??void 0;return S(await Wh(o,ye,d))}if(N.pathname==="/api/databases/vitess/migrations/action"&&I.method==="POST"){let d=await oe(I),g=String(d.uuid??"").trim(),T=String(d.action??"");if(!["retry","cancel","cleanup","complete"].includes(T))return S({ok:!1,error:"Unknown migration action."},422);return S(await Hh(o,ye,g,T))}if(N.pathname==="/api/databases/vitess/keyspaces"&&I.method==="POST"){let d=await oe(I),g=String(d.name??"").trim(),T=d.sharded===!0;return S(await Vh(o,ye,g,{sharded:T}))}if(N.pathname==="/api/databases/vitess/vschema"&&I.method==="POST"){let d=await oe(I),g=String(d.keyspace??"").trim(),T=typeof d.vschema==="string"?d.vschema:JSON.stringify(d.vschema??null);return S(await qh(o,ye,g,T))}if(N.pathname==="/api/databases/vitess/schema"&&I.method==="POST"){let d=await oe(I),g=String(d.sql??"");return S(await Jh(o,ye,g))}if(N.pathname==="/api/databases/vitess/install-client"&&I.method==="POST")return S(await zh(o,ye));if(N.pathname==="/api/databases/backups"&&I.method==="GET")return S(await Mh(o,ye));if(N.pathname==="/api/databases/backup"&&I.method==="POST"){let d=await oe(I),g=String(d.database??"").trim();if(!uo(g))return S({ok:!1,error:"Database name must be a valid identifier."},422);if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to back up this database.`},409);return S(await $h(o,ye,g))}if(N.pathname==="/api/databases/users"&&I.method==="POST"){let d=await oe(I),g=String(d.username??"").trim(),T=String(d.password??""),_=String(d.database??"").trim()||void 0,L=d.access==="readonly"?"readonly":"all";if(!uo(g))return S({ok:!1,error:"Username must be a valid identifier."},422);if(!T)return S({ok:!1,error:"Password is required."},422);if(_&&!uo(_))return S({ok:!1,error:"Database must be a valid identifier."},422);return S({...await Nh(o,ye,{username:g,password:T,database:_,access:L}),username:g})}if(N.pathname==="/api/dashboard-data")return Mt=q.get(ye)??await at(ye),at(ye),S(ql(Mt,{user:si,slug:o.project.slug}));if(N.pathname==="/api/users"&&I.method==="GET")return S({ok:!0,users:Jn(t).map(ta)});if(N.pathname==="/api/users"&&I.method==="POST"){let d=await oe(I),g=String(d.username??"").trim();if(!fd(g))return S({ok:!1,error:"Username must be 2-32 characters: letters, numbers, dot, dash or underscore."},422);let T=d.sites&&typeof d.sites==="object"?d.sites:{},_=new Set(Object.keys(o.sites??{})),L={};for(let[Q,fe]of Object.entries(T)){if(!_.has(Q))return S({ok:!1,error:`Site '${Q}' was not found.`},404);if(fe!=="owner"&&fe!=="collaborator")return S({ok:!1,error:`Unknown site role '${fe}'. Use 'owner' or 'collaborator'.`},422);L[Q]=fe}let K=typeof d.password==="string"&&d.password.trim()?d.password.trim():void 0;if(K&&K.length<12)return S({ok:!1,error:"Password must be at least 12 characters."},422);let B=La(t,{username:g,password:K,name:typeof d.name==="string"?d.name:void 0,sites:L});return sd(a,Jn(t)),gi(),S({ok:!0,user:ta(B.user),password:B.password})}if(N.pathname==="/api/users"&&I.method==="DELETE"){let d=await oe(I),g=String(d.username??"").trim();if(g.toLowerCase()===de.username.toLowerCase())return S({ok:!1,error:"You cannot remove your own account."},409);let T=pi(Jn(t),g),_=T?a.store.getActorByExternalId("user",`dashboard:${T.username.toLowerCase()}`):void 0,L=_?a.store.getMembershipForActor(a.organization.id,_.id):void 0;if(L&&L.source!=="legacy")return S({ok:!1,error:"Organization members must be removed from Organization access."},409);let K=zl(t,g);if(!K.ok)return S(K,409);return sd(a,Jn(t)),Te.clear(),S({ok:!0,username:g})}if(N.pathname==="/api/actions/run"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=d.action?sA(d.action,ye):void 0;if(!g)return S({ok:!1,error:"Unknown dashboard action."},404);if(g.mutates&&d.confirm!==g.confirm)return S({ok:!1,error:`Type "${g.confirm}" to run this action.`},409);let T=await ao({controlPlane:a,environment:ye,actor:de,kind:`dashboard.action.${g.id}`,input:{action:g.id},execute:()=>np(g,{cwd:t,cliEntry:i})});return S({...T.result,controlPlaneOperation:T.operation})}if(N.pathname==="/api/server/operations/run"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=d.operation?xn(d.operation,o,Mt):void 0;if(!g)return S({ok:!1,error:"Unknown or unavailable server operation."},404);if(g.mutates&&d.confirm!==g.confirm)return S({ok:!1,error:`Type "${g.confirm}" to run this operation.`},409);let T=ae(a,String(ye));await new ps(ct).run(new Oa,{...T,artifactRoot:t});let _=Yt(ct,{scope:T,desiredConfigHash:a.project.desiredConfigHash});if(_.decision.outcome==="block")return S({ok:!1,error:`Operation blocked by security policy: ${_.decision.explanation}`,securityReview:_},409);let L=await ao({controlPlane:a,environment:ye,actor:de,kind:`dashboard.server.${g.id}`,resourceSlug:g.target,input:{operation:g.id,target:g.target,to:d.to??null},execute:()=>Dr(o,ye,g,{to:d.to})});return S({...L.result,controlPlaneOperation:L.operation,securityReview:_})}if(N.pathname==="/api/server/command"&&I.method==="POST"){let d=await I.json().catch(()=>({}));if(d.confirm!=="run")return S({ok:!1,error:'Type "run" to execute this command on the server.'},409);let g=await ao({controlPlane:a,environment:ye,actor:de,kind:"dashboard.server.command",input:{source:"interactive-command"},execute:()=>Xt(o,ye,String(d.command??""))});return S({...g.result,controlPlaneOperation:g.operation})}if(N.pathname==="/api/serverless/operations")return S(Kl(o,ye,Mt));if(N.pathname==="/api/serverless/operations/run"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=d.operation?Cy(d.operation,o,ye,Mt):void 0;if(!g)return S({ok:!1,error:"Unknown or unavailable serverless operation."},404);if(g.mutates&&d.confirm!==g.confirm)return S({ok:!1,error:`Type "${g.confirm}" to run this operation.`},409);let T=await ao({controlPlane:a,environment:ye,actor:de,kind:`dashboard.serverless.${g.id}`,input:{operation:g.id,min:d.min??null,max:d.max??null},execute:()=>Ey(o,ye,g,{min:d.min,max:d.max})});return Mt=await bs(o,ye),q.set(ye,Mt),S({...T.result,controlPlaneOperation:T.operation})}if(N.pathname==="/api/serverless/command"&&I.method==="POST"){let d=await I.json().catch(()=>({}));if(d.confirm!=="run")return S({ok:!1,error:'Type "run" to execute this command.'},409);return S(await Ty(o,ye,String(d.command??"")))}if(N.pathname==="/api/serverless/dlq"&&I.method==="GET"){let d=Number(N.searchParams.get("max"))||10;return S(await Ay(o,ye,d))}if(N.pathname==="/api/serverless/dlq/redrive"&&I.method==="POST"){let d=await I.json().catch(()=>({}));if(d.confirm!=="redrive")return S({ok:!1,error:'Type "redrive" to move messages back onto a source queue.'},409);return S(await ky(o,ye,{max:d.max,targetQueue:d.targetQueue}))}if(N.pathname==="/api/serverless/dlq/purge"&&I.method==="POST"){if((await I.json().catch(()=>({}))).confirm!=="purge")return S({ok:!1,error:'Type "purge" to permanently discard every DLQ message.'},409);return S(await Ry(o,ye))}if(N.pathname==="/api/serverless/secrets"&&I.method==="GET")return S({secrets:Py(o,ye)});if(N.pathname==="/api/serverless/secrets"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=String(d.secretId??"").trim();if(!g)return S({ok:!1,error:"A secret id is required."},422);if(typeof d.value!=="string"||d.value==="")return S({ok:!1,error:"A non-empty value is required."},422);return S(await xy(o,ye,g,d.value))}if(N.pathname==="/api/serverless/secrets"&&I.method==="DELETE"){let d=await I.json().catch(()=>({})),g=String(d.secretId??"").trim();if(!g)return S({ok:!1,error:"A secret id is required."},422);if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to delete this secret.`},409);return S(await Dy(o,ye,g))}if(N.pathname==="/api/serverless/functions/config"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=String(d.mode??"").trim();if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to update this function.`},409);return S(await Oy(o,ye,g,{memory:d.memory,timeout:d.timeout}))}if(N.pathname==="/api/serverless/alarms"&&I.method==="GET")return S(await _y(o,ye));if(N.pathname==="/api/serverless/alarms"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=String(d.preset??"").trim(),T=Number(d.threshold);if(!g)return S({ok:!1,error:"An alarm metric is required."},422);if(!Number.isFinite(T))return S({ok:!1,error:"A numeric threshold is required."},422);return S(await Ny(o,ye,g,T))}if(N.pathname==="/api/serverless/alarms"&&I.method==="DELETE"){let d=await I.json().catch(()=>({})),g=String(d.name??"").trim();if(!g)return S({ok:!1,error:"An alarm name is required."},422);if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to delete this alarm.`},409);return S(await $y(o,ye,g))}if(N.pathname==="/api/serverless/traces"&&I.method==="GET"){let d=Number(N.searchParams.get("minutes"))||30;return S(await Sd(o,ye,d))}if(N.pathname==="/api/serverless/scheduler"&&I.method==="POST"){let d=await I.json().catch(()=>({})),g=String(d.action??"").trim();if(g!=="enable"&&g!=="disable"&&g!=="run")return S({ok:!1,error:"Unknown scheduler action."},422);if(d.confirm!==g)return S({ok:!1,error:`Type "${g}" to ${g} the scheduler.`},409);return S(await Xl(o,ye,g))}if(!ab(N.pathname,si))return new Response(null,{status:302,headers:{location:`/access-denied?env=${encodeURIComponent(ye)}`}});let Ts=await Pi(de,ye);if(!Ts)return Ed("ts-cloud dashboard UI is unavailable.",503);return cb(Ts,N.pathname)}catch(Uo){if(e.verbose)console.error(Uo);return S({ok:!1,error:Uo?.message??String(Uo)},500)}})();if(!or)return or;if(mt&&(N.pathname.startsWith("/api/")||N.pathname.startsWith("/auth/"))){let Xe;if((we.headers.get("content-type")||"").includes("application/json"))Xe=await we.json().catch(()=>{return});let Br=Bt.resolveUser(I),wr=Br?Me(Br).actor:void 0;a.store.appendEvent({organizationId:a.organization.id,projectId:a.project.id,actorId:wr?.id,correlationId:We,type:or.status<400?"dashboard.mutation.succeeded":"dashboard.mutation.failed",level:or.status<400?"info":"warning",payload:qT(I.method,N.pathname,Xe,or.status,Date.now()-Ne)})}return or.headers.set("x-request-id",We),or}});qa?.start();let Eb=e.spendLoop??!0,Cp;if(Eb)(async()=>{let{SpendRunner:I,SpendLoopLease:Ce,startSpendLoop:Ne}=await import("./chunk-jh1593zx.js"),{store:we}=await ub(a.store),We=new I({controlPlane:a.store,store:we,alerts:Ge});Cp=Ne(We,{lease:new Ce(a.store,{owner:`dashboard:${process.pid}`}),onError:(mt)=>console.error(`[ts-cloud] spend cycle failed: ${mt instanceof Error?mt.message:String(mt)}`)})})();let Tb=Is.stop.bind(Is);return Is.stop=(I)=>{clearInterval(Sp),clearInterval(vp),clearInterval(wp),clearInterval(bp),clearInterval(yp),clearInterval(gp),clearInterval(mp),clearInterval(fp),clearInterval(hp),gi(),ar.clear(),qa?.stop(),Cp?.();let Ce=Tb(I);if(qa)qa.settled().finally(()=>a.store.close());else a.store.close();return Ce},{server:Is,url:`http://${r}:${Is.port}/`}}
|
|
511
|
+
export{De,D,cn,y,ln,Ei,dn,Do,Ir,Ye,Ae,un,pn,mn,gn,fn,hn,yn,Sn,te,qt,Ht,bn,Rr,vn,Tn,En,wn,Cn,An,In,Rn,Ze,Wt,Gt,Ct,Pr,Kt,Jt,wi,At,Pn,se,Nn,kn,Dn,Nr,kr,xn,Dr,Xt,Qt,et,It,Rt,xr,ae,_n,na,ia,Yt,oa,z,Ci,Ue,tt,rt,$n,_r,$r,On,Ln,Mn,Or,xo,ce,me,xe,ge,Un,Zt};
|