@stacksjs/ts-cloud 0.16.84 → 0.16.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/aws/index.js +1 -1
  2. package/dist/bin/{chunk-sbm0ft8c.js → chunk-0e56zmps.js} +1 -1
  3. package/dist/bin/{chunk-vr9jcw65.js → chunk-1vw6khps.js} +1 -1
  4. package/dist/bin/{chunk-j1dpdjec.js → chunk-2dbyh1g2.js} +5 -5
  5. package/dist/bin/{chunk-b61yq5rn.js → chunk-4k2x5x3k.js} +1 -1
  6. package/dist/bin/{chunk-c4krzg7x.js → chunk-4mep3m41.js} +1 -1
  7. package/dist/bin/{chunk-7477zgt9.js → chunk-6wvjr3ne.js} +1 -1
  8. package/dist/bin/{chunk-kvwm9z1r.js → chunk-71fa7yed.js} +1 -1
  9. package/dist/bin/{chunk-hkgbbph1.js → chunk-76ekkat8.js} +1 -1
  10. package/dist/bin/chunk-7aqzsbak.js +1 -0
  11. package/dist/bin/{chunk-7yhy2a7h.js → chunk-86w3vzx8.js} +1 -1
  12. package/dist/bin/chunk-8tfqpp9m.js +1 -0
  13. package/dist/bin/{chunk-5xvvxh1f.js → chunk-9bmaq8q7.js} +8 -8
  14. package/dist/bin/chunk-9tt7ahdf.js +1 -0
  15. package/dist/bin/{chunk-08sws53b.js → chunk-bxks81wn.js} +2 -2
  16. package/dist/bin/{chunk-9p6hkb64.js → chunk-bycbwddj.js} +1 -1
  17. package/dist/bin/{chunk-mhmvr5w3.js → chunk-em9swj0k.js} +1 -1
  18. package/dist/bin/{chunk-2bghtp9b.js → chunk-ff3x4pgw.js} +1 -1
  19. package/dist/bin/{chunk-r5zsebn5.js → chunk-g9820x34.js} +28 -28
  20. package/dist/bin/{chunk-8dzqjsz1.js → chunk-mwprtzxp.js} +1 -1
  21. package/dist/bin/chunk-ndjpa2tq.js +1 -0
  22. package/dist/bin/{chunk-yd2vnd4y.js → chunk-ndvma07s.js} +1 -1
  23. package/dist/bin/{chunk-ydbvafmk.js → chunk-nemj07g1.js} +1 -1
  24. package/dist/bin/{chunk-rpsnnr53.js → chunk-nfxxr6g7.js} +1 -1
  25. package/dist/bin/{chunk-f1jkvaxm.js → chunk-v1a0b9yq.js} +8 -8
  26. package/dist/bin/{chunk-8erhr0vh.js → chunk-v3trt4q1.js} +2 -2
  27. package/dist/bin/{chunk-cbb6wqqz.js → chunk-xkp5r2ye.js} +90 -90
  28. package/dist/bin/{chunk-eqw1dk00.js → chunk-xycxw00z.js} +7 -7
  29. package/dist/bin/cli.js +147 -147
  30. package/dist/bin/dashboard-server.js +1 -1
  31. package/dist/chunk-03gf4e58.js +1 -0
  32. package/dist/{chunk-pbkev5pe.js → chunk-2yqvgbmn.js} +39 -39
  33. package/dist/{chunk-q61qcpp4.js → chunk-3bvhthfb.js} +14 -14
  34. package/dist/{chunk-42vtybcm.js → chunk-4pztf7ws.js} +3 -3
  35. package/dist/{chunk-rq650jaz.js → chunk-5t92a838.js} +10 -10
  36. package/dist/{chunk-18dqxyz5.js → chunk-8kn7rszy.js} +1 -1
  37. package/dist/{chunk-8drf81qf.js → chunk-ax320pn8.js} +1 -1
  38. package/dist/{chunk-dvw5dy32.js → chunk-cq079p4a.js} +4 -4
  39. package/dist/{chunk-pk8ppz98.js → chunk-e75dvdqf.js} +2 -2
  40. package/dist/{chunk-0f23y8ba.js → chunk-fpad8xw9.js} +1 -1
  41. package/dist/{chunk-cz4dw2hk.js → chunk-gdw52mn4.js} +2 -2
  42. package/dist/{chunk-bhbv9qqn.js → chunk-gpgmp9dt.js} +1 -1
  43. package/dist/{chunk-kcb203be.js → chunk-m35z9vyn.js} +1 -1
  44. package/dist/{chunk-tb5hy7rm.js → chunk-ncet7ba7.js} +1 -1
  45. package/dist/{chunk-7ea0q5tg.js → chunk-py8dq1ey.js} +4 -4
  46. package/dist/{chunk-rec9q5vz.js → chunk-s56rah0t.js} +99 -99
  47. package/dist/{chunk-xyhh44eq.js → chunk-tr54e9c0.js} +1 -1
  48. package/dist/deploy/index.js +1 -1
  49. package/dist/dns/index.js +1 -1
  50. package/dist/drivers/hetzner/client.d.ts +6 -0
  51. package/dist/drivers/hetzner/driver.d.ts +1 -0
  52. package/dist/drivers/hetzner/reverse-dns.d.ts +6 -0
  53. package/dist/drivers/index.js +1 -1
  54. package/dist/index.js +16 -16
  55. package/dist/mail/index.js +1 -1
  56. package/dist/operations/index.js +1 -1
  57. package/dist/protection/index.js +1 -1
  58. package/dist/spend/index.js +1 -1
  59. package/dist/ui/404.html +1 -1
  60. package/dist/ui/accept-invitation.html +1 -1
  61. package/dist/ui/access-denied.html +1 -1
  62. package/dist/ui/account/automation.html +5 -5
  63. package/dist/ui/account/security.html +2 -2
  64. package/dist/ui/applications/compose.html +6 -6
  65. package/dist/ui/applications/new.html +2 -2
  66. package/dist/ui/data/backups.html +6 -6
  67. package/dist/ui/data/services.html +6 -6
  68. package/dist/ui/data/volumes.html +6 -6
  69. package/dist/ui/index.html +6 -6
  70. package/dist/ui/infrastructure/topology.html +5 -5
  71. package/dist/ui/integrations.html +1 -1
  72. package/dist/ui/operations/alerts.html +6 -6
  73. package/dist/ui/operations/configuration.html +6 -6
  74. package/dist/ui/operations/jobs.html +6 -6
  75. package/dist/ui/operations/maintenance.html +5 -5
  76. package/dist/ui/operations/observability.html +6 -6
  77. package/dist/ui/operations/previews.html +6 -6
  78. package/dist/ui/operations/queue.html +6 -6
  79. package/dist/ui/operations/regions.html +5 -5
  80. package/dist/ui/operations/releases.html +6 -6
  81. package/dist/ui/operations/spend.html +5 -5
  82. package/dist/ui/operations/workloads.html +6 -6
  83. package/dist/ui/security.html +1 -1
  84. package/dist/ui/server/actions.html +6 -6
  85. package/dist/ui/server/activity.html +2 -2
  86. package/dist/ui/server/capacity.html +5 -5
  87. package/dist/ui/server/database.html +5 -5
  88. package/dist/ui/server/deployments.html +6 -6
  89. package/dist/ui/server/diagnostics.html +2 -2
  90. package/dist/ui/server/firewall.html +6 -6
  91. package/dist/ui/server/fleet.html +6 -6
  92. package/dist/ui/server/logs.html +6 -6
  93. package/dist/ui/server/metrics.html +6 -6
  94. package/dist/ui/server/security.html +2 -2
  95. package/dist/ui/server/services.html +1 -1
  96. package/dist/ui/server/sites.html +6 -6
  97. package/dist/ui/server/ssh-keys.html +6 -6
  98. package/dist/ui/server/team.html +6 -6
  99. package/dist/ui/server/terminal.html +2 -2
  100. package/dist/ui/serverless/alarms.html +6 -6
  101. package/dist/ui/serverless/assets.html +2 -2
  102. package/dist/ui/serverless/cost.html +2 -2
  103. package/dist/ui/serverless/data.html +6 -6
  104. package/dist/ui/serverless/deployments.html +2 -2
  105. package/dist/ui/serverless/firewall.html +1 -1
  106. package/dist/ui/serverless/functions.html +6 -6
  107. package/dist/ui/serverless/logs.html +6 -6
  108. package/dist/ui/serverless/metrics.html +2 -2
  109. package/dist/ui/serverless/queues.html +6 -6
  110. package/dist/ui/serverless/secrets.html +6 -6
  111. package/dist/ui/serverless/traces.html +6 -6
  112. package/dist/ui/serverless.html +5 -5
  113. package/package.json +3 -3
  114. package/dist/bin/chunk-1nnt30xt.js +0 -1
  115. package/dist/bin/chunk-24g6snzv.js +0 -1
  116. package/dist/bin/chunk-4a9p7fd0.js +0 -1
  117. package/dist/bin/chunk-q82s4yzg.js +0 -1
  118. package/dist/chunk-2ntc2qz2.js +0 -1
@@ -1,4 +1,4 @@
1
- import{Q,l}from"./chunk-q61qcpp4.js";import{cn}from"./chunk-84z2a1xn.js";var Je=40,yd=[{version:1,name:"core_control_plane",sql:`
1
+ import{Q,l}from"./chunk-3bvhthfb.js";import{cn}from"./chunk-84z2a1xn.js";var Je=40,yd=[{version:1,name:"core_control_plane",sql:`
2
2
  CREATE TABLE projects (
3
3
  id TEXT PRIMARY KEY,
4
4
  slug TEXT NOT NULL UNIQUE,
@@ -1475,8 +1475,8 @@ import{Q,l}from"./chunk-q61qcpp4.js";import{cn}from"./chunk-84z2a1xn.js";var Je=
1475
1475
  -- once a minute, forever.
1476
1476
  CREATE INDEX telemetry_kind_scope_time_idx
1477
1477
  ON telemetry_records(project_id, kind, timestamp);
1478
- `}];import{createHash as _e,randomBytes as yr}from"node:crypto";import{chmodSync as He,existsSync as _t,mkdirSync as Lr,statSync as vr}from"node:fs";import{dirname as ht}from"node:path";import{Database as Ir}from"bun:sqlite";var be=["project:read","config:read","config:write","deployments:read","deployments:create","deployments:cancel","deployments:rollback","runtime:read","runtime:restart","runtime:logs","runtime:terminal","data:read","data:write","data:admin","backups:read","backups:create","backups:restore","secrets:read","secrets:write","fleet:read","fleet:manage","users:read","users:manage","users:transfer-ownership","audit:read","billing:read","billing:manage","security:read","security:manage","security:waive","sources:read","sources:manage","applications:read","applications:manage","automation:read","automation:manage","tags:manage"],qe=["project:read","config:read","deployments:read","runtime:read","runtime:logs","data:read","backups:read","security:read","sources:read","applications:read","billing:read"],fr={owner:new Set(be),admin:new Set(be.filter((e)=>e!=="users:transfer-ownership")),deployer:new Set([...qe,"deployments:create","deployments:cancel","deployments:rollback","sources:manage","applications:manage"]),operator:new Set([...qe,"runtime:restart","backups:create","security:manage","sources:manage","applications:manage"]),viewer:new Set(qe),auditor:new Set(["project:read","config:read","deployments:read","runtime:read","data:read","backups:read","audit:read","security:read","sources:read","applications:read"])};function nr(e){return fr[e]}function Sd(e,t){if(e.type==="organization")return e.id===void 0||e.id===t.organizationId;if(!e.id)return!1;if(e.type==="project")return e.id===t.projectId;if(e.type==="environment")return e.id===t.environmentId;return e.id===t.resourceId}function x(e){let{membership:t,capability:r,target:n}=e;if(!t||t.status!=="active"||t.organizationId!==n.organizationId)return{allowed:!1,reason:"inactive-membership"};let o=e.grants.filter((u)=>u.organizationId===n.organizationId&&u.membershipId===t.id&&u.capability===r&&Sd(u.scope,n)),a=o.find((u)=>u.effect==="deny");if(a)return{allowed:!1,reason:"explicit-deny",inheritedFrom:{kind:"grant",id:a.id,scope:a.scope}};let d=o.find((u)=>u.effect==="allow");if(d)return{allowed:!0,reason:"explicit-allow",inheritedFrom:{kind:"grant",id:d.id,scope:d.scope}};if(!Sd(t.scope,n))return{allowed:!1,reason:"scope-mismatch"};if(nr(t.roleTemplate).has(r))return{allowed:!0,reason:"role-template",inheritedFrom:{kind:"membership",id:t.id,scope:t.scope}};return{allowed:!1,reason:"missing-capability"}}function ir(e){return be.filter((t)=>x({...e,capability:t}).allowed)}class wt extends Error{constructor(e,t,r){super(`${e} ${t} changed since version ${r}`);this.name="OptimisticConcurrencyError"}}class Id extends Error{constructor(e,t){super(`Operation cannot transition from ${e} to ${t}`);this.name="InvalidOperationTransitionError"}}class yo extends Error{constructor(e,t){super(`Control-plane schema version ${e} is newer than supported version ${t}`);this.name="UnsupportedSchemaVersionError"}}function DA(){return Q("control-plane.sqlite")}var Wp=65536,bd=16384,Sr=["succeeded","failed","cancelled","timed_out"],br={queued:["running","cancelled","timed_out"],running:["queued","succeeded","failed","cancelled","timed_out"],succeeded:[],failed:["queued"],cancelled:["queued"],timed_out:["queued"]},Rr=/(?:^|_)(?:authorization|cookie|credential|password|passwd|secret|token|api_?key|private_?key|access_?key)(?:$|_)/i,Nt=/(?:authorization|password|secret|token|api[_-]?key|private[_-]?key|access[_-]?key)\s*[=:]\s*[^\s,;]+/gi;function F(e){if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}}function S(e){return typeof e==="string"?e:void 0}function Ke(e,t){if(t&&Rr.test(t))return"[REDACTED]";if(e===null||typeof e==="boolean"||typeof e==="number")return e;if(typeof e==="string")return e.replace(Nt,"[REDACTED]");if(Array.isArray(e))return e.map((r)=>Ke(r));if(e&&typeof e==="object"){let r={};for(let[n,o]of Object.entries(e))r[n]=Ke(o,n);return r}return String(e??"")}function s(e,t=Wp){let r=Ke(e),n=JSON.stringify(r);if(Buffer.byteLength(n)<=t)return r;return{truncated:!0,originalBytes:Buffer.byteLength(n),preview:n.slice(0,Math.max(0,t-128))}}function b(e){return JSON.stringify(s(e))}function Be(e){if(!e)return;let t=e.replace(Nt,"[REDACTED]");return Buffer.byteLength(t)<=bd?t:`${t.slice(0,bd-24)}
1479
- [output truncated]`}function he(e){return{id:String(e.id),slug:String(e.slug),name:String(e.name),description:S(e.description),organizationId:S(e.organization_id),desiredConfigHash:S(e.desired_config_hash),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ne(e){return{id:String(e.id),projectId:String(e.project_id),slug:String(e.slug),name:String(e.name),kind:String(e.kind),region:S(e.region),desiredState:F(e.desired_state),discoveredState:F(e.discovered_state),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function fe(e){return{id:String(e.id),projectId:String(e.project_id),environmentId:S(e.environment_id),kind:String(e.kind),slug:String(e.slug),name:String(e.name),provider:S(e.provider),providerId:S(e.provider_id),desiredState:F(e.desired_state),discoveredState:F(e.discovered_state),metadata:F(e.metadata),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ye(e){return{id:String(e.id),kind:String(e.kind),externalId:S(e.external_id),displayName:String(e.display_name),metadata:F(e.metadata),disabledAt:S(e.disabled_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function K(e){return{id:String(e.id),projectId:S(e.project_id),environmentId:S(e.environment_id),resourceId:S(e.resource_id),actorId:S(e.actor_id),kind:String(e.kind),state:String(e.state),correlationId:String(e.correlation_id),idempotencyKey:S(e.idempotency_key),input:F(e.input),output:F(e.output),error:S(e.error),attempt:Number(e.attempt),priority:Number(e.priority),leaseOwner:S(e.lease_owner),leaseExpiresAt:S(e.lease_expires_at),cancelRequestedAt:S(e.cancel_requested_at),startedAt:S(e.started_at),finishedAt:S(e.finished_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ve(e){return{id:String(e.id),sequence:Number(e.sequence),organizationId:S(e.organization_id),projectId:S(e.project_id),operationId:S(e.operation_id),resourceId:S(e.resource_id),actorId:S(e.actor_id),correlationId:String(e.correlation_id),type:String(e.type),level:String(e.level),payload:F(e.payload),createdAt:String(e.created_at)}}function ie(e){return{id:String(e.id),projectId:String(e.project_id),name:String(e.name),normalizedName:String(e.normalized_name),color:String(e.color),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Le(e){return{id:String(e.id),actorKey:String(e.actor_key),name:String(e.name),routeId:String(e.route_id),query:F(e.query),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ve(e){return{actorKey:String(e.actor_key),entityType:String(e.entity_type),entityId:String(e.entity_id),favorite:Number(e.favorite)===1,lastVisitedAt:String(e.last_visited_at),visitCount:Number(e.visit_count)}}function Ie(e){return{id:String(e.id),slug:String(e.slug),name:String(e.name),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function $e(e){let t=String(e.scope_type);return{type:t,...t==="organization"?{}:{id:String(e.scope_id)}}}function Se(e){return{id:String(e.id),organizationId:String(e.organization_id),actorId:String(e.actor_id),roleTemplate:String(e.role_template),scope:$e(e),source:String(e.source??"manual"),status:String(e.status),sessionVersion:Number(e.session_version),lastActiveAt:S(e.last_active_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function oe(e,t){let r=S(e.accepted_at),n=S(e.revoked_at),o=String(e.expires_at),a=n?"revoked":r?"accepted":o<=t?"expired":"pending";return{id:String(e.id),organizationId:String(e.organization_id),email:String(e.email),roleTemplate:String(e.role_template),scope:$e(e),invitedByActorId:S(e.invited_by_actor_id),acceptedByActorId:S(e.accepted_by_actor_id),expiresAt:o,acceptedAt:r,revokedAt:n,state:a,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Re(e){return{id:String(e.id),organizationId:String(e.organization_id),membershipId:String(e.membership_id),effect:String(e.effect),capability:String(e.capability),scope:$e(e),source:String(e.source??"manual"),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function se(e){return{type:e.type,id:e.id??null}}function Cr(e){return Array.from({length:e},()=>"?").join(", ")}function f(e,t,r){return e.run(t,r)}class Li{path;database;nowFn;idFn;constructor(e={}){this.path=e.path??l(e.cwd??process.cwd(),"control-plane.sqlite"),this.nowFn=e.now??(()=>new Date),this.idFn=e.id??(()=>crypto.randomUUID());let t=this.path===":memory:";if(!t){Lr(ht(this.path),{recursive:!0,mode:448});try{He(ht(this.path),448)}catch{}}if(this.database=new Ir(this.path,{create:!0,strict:!0}),this.database.run("PRAGMA foreign_keys = ON"),this.database.run(`PRAGMA busy_timeout = ${Math.max(100,e.busyTimeoutMs??5000)}`),!t)this.database.run("PRAGMA journal_mode = WAL"),this.database.run("PRAGMA synchronous = NORMAL");if(this.migrate(),!t)this.secureDatabaseFiles()}now(){return this.nowFn().toISOString()}secureDatabaseFiles(){for(let e of[this.path,`${this.path}-wal`,`${this.path}-shm`]){if(!_t(e))continue;try{He(e,384)}catch{}}}backupTo(e){this.database.run("VACUUM INTO ?",[e]);try{He(e,384)}catch{}}migrate(){let e=this.database.query("PRAGMA user_version").get(),t=Number(e?.user_version??0);if(t>Je)throw new yo(t,Je);if(t===Je)return;let r;if(t>0&&this.path!==":memory:")r=`${this.path}.v${t}.${Date.now()}.bak`,this.backupTo(r);try{if(this.database.transaction(()=>{for(let o of yd){if(o.version<=t)continue;this.database.run(o.sql),f(this.database,"INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",[o.version,o.name,this.now()]),this.database.run(`PRAGMA user_version = ${o.version}`)}}).exclusive(),r)this.setSetting("storage.last_backup",{path:r,createdAt:this.now(),reason:"pre-migration"})}catch(n){let o=r?` Restore from ${r}.`:"";throw Error(`Control-plane migration from schema ${t} failed.${o} ${n instanceof Error?n.message:String(n)}`)}}close(){if(this.path!==":memory:")this.secureDatabaseFiles();this.database.close()}transaction(e){return this.database.transaction(e).immediate()}createProject(e){let t=e.id??this.idFn(),r=this.now();return f(this.database,"INSERT INTO projects (id, slug, name, description, organization_id, desired_config_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",[t,e.slug,e.name,e.description??null,e.organizationId??null,e.desiredConfigHash??null,r,r]),this.getProject(t)}getProject(e){let t=this.database.query("SELECT * FROM projects WHERE id = ?").get(e);return t?he(t):void 0}getProjectBySlug(e){let t=this.database.query("SELECT * FROM projects WHERE slug = ?").get(e);return t?he(t):void 0}listProjects(){return this.database.query("SELECT * FROM projects ORDER BY name COLLATE NOCASE, id").all().map(he)}updateProject(e,t,r){let n=this.getProject(e);if(!n||n.version!==t)throw new wt("Project",e,t);if(f(this.database,`UPDATE projects SET name = ?, description = ?, organization_id = ?, desired_config_hash = ?, version = version + 1, updated_at = ?
1478
+ `}];import{createHash as _e,randomBytes as yr}from"node:crypto";import{chmodSync as He,existsSync as _t,mkdirSync as Lr,statSync as vr}from"node:fs";import{dirname as ht}from"node:path";import{Database as Ir}from"bun:sqlite";var Ce=["project:read","config:read","config:write","deployments:read","deployments:create","deployments:cancel","deployments:rollback","runtime:read","runtime:restart","runtime:logs","runtime:terminal","data:read","data:write","data:admin","backups:read","backups:create","backups:restore","secrets:read","secrets:write","fleet:read","fleet:manage","users:read","users:manage","users:transfer-ownership","audit:read","billing:read","billing:manage","security:read","security:manage","security:waive","sources:read","sources:manage","applications:read","applications:manage","automation:read","automation:manage","tags:manage"],qe=["project:read","config:read","deployments:read","runtime:read","runtime:logs","data:read","backups:read","security:read","sources:read","applications:read","billing:read"],fr={owner:new Set(Ce),admin:new Set(Ce.filter((e)=>e!=="users:transfer-ownership")),deployer:new Set([...qe,"deployments:create","deployments:cancel","deployments:rollback","sources:manage","applications:manage"]),operator:new Set([...qe,"runtime:restart","backups:create","security:manage","sources:manage","applications:manage"]),viewer:new Set(qe),auditor:new Set(["project:read","config:read","deployments:read","runtime:read","data:read","backups:read","audit:read","security:read","sources:read","applications:read"])};function nr(e){return fr[e]}function Sd(e,t){if(e.type==="organization")return e.id===void 0||e.id===t.organizationId;if(!e.id)return!1;if(e.type==="project")return e.id===t.projectId;if(e.type==="environment")return e.id===t.environmentId;return e.id===t.resourceId}function x(e){let{membership:t,capability:r,target:n}=e;if(!t||t.status!=="active"||t.organizationId!==n.organizationId)return{allowed:!1,reason:"inactive-membership"};let o=e.grants.filter((u)=>u.organizationId===n.organizationId&&u.membershipId===t.id&&u.capability===r&&Sd(u.scope,n)),a=o.find((u)=>u.effect==="deny");if(a)return{allowed:!1,reason:"explicit-deny",inheritedFrom:{kind:"grant",id:a.id,scope:a.scope}};let d=o.find((u)=>u.effect==="allow");if(d)return{allowed:!0,reason:"explicit-allow",inheritedFrom:{kind:"grant",id:d.id,scope:d.scope}};if(!Sd(t.scope,n))return{allowed:!1,reason:"scope-mismatch"};if(nr(t.roleTemplate).has(r))return{allowed:!0,reason:"role-template",inheritedFrom:{kind:"membership",id:t.id,scope:t.scope}};return{allowed:!1,reason:"missing-capability"}}function ir(e){return Ce.filter((t)=>x({...e,capability:t}).allowed)}class wt extends Error{constructor(e,t,r){super(`${e} ${t} changed since version ${r}`);this.name="OptimisticConcurrencyError"}}class Id extends Error{constructor(e,t){super(`Operation cannot transition from ${e} to ${t}`);this.name="InvalidOperationTransitionError"}}class yo extends Error{constructor(e,t){super(`Control-plane schema version ${e} is newer than supported version ${t}`);this.name="UnsupportedSchemaVersionError"}}function DA(){return Q("control-plane.sqlite")}var Wp=65536,bd=16384,Sr=["succeeded","failed","cancelled","timed_out"],br={queued:["running","cancelled","timed_out"],running:["queued","succeeded","failed","cancelled","timed_out"],succeeded:[],failed:["queued"],cancelled:["queued"],timed_out:["queued"]},Rr=/(?:^|_)(?:authorization|cookie|credential|password|passwd|secret|token|api_?key|private_?key|access_?key)(?:$|_)/i,Nt=/(?:authorization|password|secret|token|api[_-]?key|private[_-]?key|access[_-]?key)\s*[=:]\s*[^\s,;]+/gi;function F(e){if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}}function S(e){return typeof e==="string"?e:void 0}function Ke(e,t){if(t&&Rr.test(t))return"[REDACTED]";if(e===null||typeof e==="boolean"||typeof e==="number")return e;if(typeof e==="string")return e.replace(Nt,"[REDACTED]");if(Array.isArray(e))return e.map((r)=>Ke(r));if(e&&typeof e==="object"){let r={};for(let[n,o]of Object.entries(e))r[n]=Ke(o,n);return r}return String(e??"")}function s(e,t=Wp){let r=Ke(e),n=JSON.stringify(r);if(Buffer.byteLength(n)<=t)return r;return{truncated:!0,originalBytes:Buffer.byteLength(n),preview:n.slice(0,Math.max(0,t-128))}}function b(e){return JSON.stringify(s(e))}function Be(e){if(!e)return;let t=e.replace(Nt,"[REDACTED]");return Buffer.byteLength(t)<=bd?t:`${t.slice(0,bd-24)}
1479
+ [output truncated]`}function he(e){return{id:String(e.id),slug:String(e.slug),name:String(e.name),description:S(e.description),organizationId:S(e.organization_id),desiredConfigHash:S(e.desired_config_hash),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ne(e){return{id:String(e.id),projectId:String(e.project_id),slug:String(e.slug),name:String(e.name),kind:String(e.kind),region:S(e.region),desiredState:F(e.desired_state),discoveredState:F(e.discovered_state),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function fe(e){return{id:String(e.id),projectId:String(e.project_id),environmentId:S(e.environment_id),kind:String(e.kind),slug:String(e.slug),name:String(e.name),provider:S(e.provider),providerId:S(e.provider_id),desiredState:F(e.desired_state),discoveredState:F(e.discovered_state),metadata:F(e.metadata),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ye(e){return{id:String(e.id),kind:String(e.kind),externalId:S(e.external_id),displayName:String(e.display_name),metadata:F(e.metadata),disabledAt:S(e.disabled_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function K(e){return{id:String(e.id),projectId:S(e.project_id),environmentId:S(e.environment_id),resourceId:S(e.resource_id),actorId:S(e.actor_id),kind:String(e.kind),state:String(e.state),correlationId:String(e.correlation_id),idempotencyKey:S(e.idempotency_key),input:F(e.input),output:F(e.output),error:S(e.error),attempt:Number(e.attempt),priority:Number(e.priority),leaseOwner:S(e.lease_owner),leaseExpiresAt:S(e.lease_expires_at),cancelRequestedAt:S(e.cancel_requested_at),startedAt:S(e.started_at),finishedAt:S(e.finished_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ve(e){return{id:String(e.id),sequence:Number(e.sequence),organizationId:S(e.organization_id),projectId:S(e.project_id),operationId:S(e.operation_id),resourceId:S(e.resource_id),actorId:S(e.actor_id),correlationId:String(e.correlation_id),type:String(e.type),level:String(e.level),payload:F(e.payload),createdAt:String(e.created_at)}}function ie(e){return{id:String(e.id),projectId:String(e.project_id),name:String(e.name),normalizedName:String(e.normalized_name),color:String(e.color),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Le(e){return{id:String(e.id),actorKey:String(e.actor_key),name:String(e.name),routeId:String(e.route_id),query:F(e.query),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ve(e){return{actorKey:String(e.actor_key),entityType:String(e.entity_type),entityId:String(e.entity_id),favorite:Number(e.favorite)===1,lastVisitedAt:String(e.last_visited_at),visitCount:Number(e.visit_count)}}function Ie(e){return{id:String(e.id),slug:String(e.slug),name:String(e.name),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function $e(e){let t=String(e.scope_type);return{type:t,...t==="organization"?{}:{id:String(e.scope_id)}}}function Se(e){return{id:String(e.id),organizationId:String(e.organization_id),actorId:String(e.actor_id),roleTemplate:String(e.role_template),scope:$e(e),source:String(e.source??"manual"),status:String(e.status),sessionVersion:Number(e.session_version),lastActiveAt:S(e.last_active_at),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function oe(e,t){let r=S(e.accepted_at),n=S(e.revoked_at),o=String(e.expires_at),a=n?"revoked":r?"accepted":o<=t?"expired":"pending";return{id:String(e.id),organizationId:String(e.organization_id),email:String(e.email),roleTemplate:String(e.role_template),scope:$e(e),invitedByActorId:S(e.invited_by_actor_id),acceptedByActorId:S(e.accepted_by_actor_id),expiresAt:o,acceptedAt:r,revokedAt:n,state:a,createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function be(e){return{id:String(e.id),organizationId:String(e.organization_id),membershipId:String(e.membership_id),effect:String(e.effect),capability:String(e.capability),scope:$e(e),source:String(e.source??"manual"),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function se(e){return{type:e.type,id:e.id??null}}function Cr(e){return Array.from({length:e},()=>"?").join(", ")}function f(e,t,r){return e.run(t,r)}class Li{path;database;nowFn;idFn;constructor(e={}){this.path=e.path??l(e.cwd??process.cwd(),"control-plane.sqlite"),this.nowFn=e.now??(()=>new Date),this.idFn=e.id??(()=>crypto.randomUUID());let t=this.path===":memory:";if(!t){Lr(ht(this.path),{recursive:!0,mode:448});try{He(ht(this.path),448)}catch{}}if(this.database=new Ir(this.path,{create:!0,strict:!0}),this.database.run("PRAGMA foreign_keys = ON"),this.database.run(`PRAGMA busy_timeout = ${Math.max(100,e.busyTimeoutMs??5000)}`),!t)this.database.run("PRAGMA journal_mode = WAL"),this.database.run("PRAGMA synchronous = NORMAL");if(this.migrate(),!t)this.secureDatabaseFiles()}now(){return this.nowFn().toISOString()}secureDatabaseFiles(){for(let e of[this.path,`${this.path}-wal`,`${this.path}-shm`]){if(!_t(e))continue;try{He(e,384)}catch{}}}backupTo(e){this.database.run("VACUUM INTO ?",[e]);try{He(e,384)}catch{}}migrate(){let e=this.database.query("PRAGMA user_version").get(),t=Number(e?.user_version??0);if(t>Je)throw new yo(t,Je);if(t===Je)return;let r;if(t>0&&this.path!==":memory:")r=`${this.path}.v${t}.${Date.now()}.bak`,this.backupTo(r);try{if(this.database.transaction(()=>{for(let o of yd){if(o.version<=t)continue;this.database.run(o.sql),f(this.database,"INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",[o.version,o.name,this.now()]),this.database.run(`PRAGMA user_version = ${o.version}`)}}).exclusive(),r)this.setSetting("storage.last_backup",{path:r,createdAt:this.now(),reason:"pre-migration"})}catch(n){let o=r?` Restore from ${r}.`:"";throw Error(`Control-plane migration from schema ${t} failed.${o} ${n instanceof Error?n.message:String(n)}`)}}close(){if(this.path!==":memory:")this.secureDatabaseFiles();this.database.close()}transaction(e){return this.database.transaction(e).immediate()}createProject(e){let t=e.id??this.idFn(),r=this.now();return f(this.database,"INSERT INTO projects (id, slug, name, description, organization_id, desired_config_hash, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",[t,e.slug,e.name,e.description??null,e.organizationId??null,e.desiredConfigHash??null,r,r]),this.getProject(t)}getProject(e){let t=this.database.query("SELECT * FROM projects WHERE id = ?").get(e);return t?he(t):void 0}getProjectBySlug(e){let t=this.database.query("SELECT * FROM projects WHERE slug = ?").get(e);return t?he(t):void 0}listProjects(){return this.database.query("SELECT * FROM projects ORDER BY name COLLATE NOCASE, id").all().map(he)}updateProject(e,t,r){let n=this.getProject(e);if(!n||n.version!==t)throw new wt("Project",e,t);if(f(this.database,`UPDATE projects SET name = ?, description = ?, organization_id = ?, desired_config_hash = ?, version = version + 1, updated_at = ?
1480
1480
  WHERE id = ? AND version = ?`,[r.name??n.name,r.description===null?null:r.description??n.description??null,r.organizationId===null?null:r.organizationId??n.organizationId??null,r.desiredConfigHash===null?null:r.desiredConfigHash??n.desiredConfigHash??null,this.now(),e,t]).changes!==1)throw new wt("Project",e,t);return this.getProject(e)}createEnvironment(e){let t=e.id??this.idFn(),r=this.now();return f(this.database,`INSERT INTO environments (id, project_id, slug, name, kind, region, desired_state, discovered_state, created_at, updated_at)
1481
1481
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[t,e.projectId,e.slug,e.name,e.kind,e.region??null,b(e.desiredState??{}),b(e.discoveredState??{}),r,r]),Ne(this.database.query("SELECT * FROM environments WHERE id = ?").get(t))}listEnvironments(e){return this.database.query("SELECT * FROM environments WHERE project_id = ? ORDER BY name COLLATE NOCASE, id").all(e).map(Ne)}getEnvironmentBySlug(e,t){let r=this.database.query("SELECT * FROM environments WHERE project_id = ? AND slug = ?").get(e,t);return r?Ne(r):void 0}createResource(e){let t=e.id??this.idFn(),r=this.now();return f(this.database,`INSERT INTO resources (id, project_id, environment_id, kind, slug, name, provider, provider_id, desired_state, discovered_state, metadata, created_at, updated_at)
1482
1482
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[t,e.projectId,e.environmentId??null,e.kind,e.slug,e.name,e.provider??null,e.providerId??null,b(e.desiredState??{}),b(e.discoveredState??{}),b(e.metadata??{}),r,r]),fe(this.database.query("SELECT * FROM resources WHERE id = ?").get(t))}listResources(e,t){return(t?this.database.query("SELECT * FROM resources WHERE project_id = ? AND environment_id = ? ORDER BY kind, name COLLATE NOCASE").all(e,t):this.database.query("SELECT * FROM resources WHERE project_id = ? ORDER BY kind, name COLLATE NOCASE").all(e)).map(fe)}getResource(e){let t=this.database.query("SELECT * FROM resources WHERE id = ?").get(e);return t?fe(t):void 0}updateResource(e,t,r){let n=this.getResource(e);if(!n||n.version!==t)throw new wt("Resource",e,t);if(f(this.database,`UPDATE resources SET name = ?, provider = ?, provider_id = ?, desired_state = ?, discovered_state = ?, metadata = ?,
@@ -1484,8 +1484,8 @@ import{Q,l}from"./chunk-q61qcpp4.js";import{cn}from"./chunk-84z2a1xn.js";var Je=
1484
1484
  WHERE organization_memberships.actor_id = ? AND organization_memberships.status = 'active' ORDER BY organizations.name COLLATE NOCASE`).all(e):this.database.query("SELECT * FROM organizations ORDER BY name COLLATE NOCASE").all()).map(Ie)}normalizeAuthorizationScope(e,t={type:"organization"}){if(t.type==="organization"){if(t.id&&t.id!==e)throw Error("Organization scope does not match the requested organization");return{type:"organization"}}if(!t.id)throw Error(`${t.type} scopes require an ID`);if(!this.resolveAuthorizationTarget(e,t))throw Error("Authorization scope was not found in this organization");return{type:t.type,id:t.id}}resolveAuthorizationTarget(e,t){if(!this.getOrganization(e))return;if(t.type==="organization")return{organizationId:e};if(!t.id)return;if(t.type==="project"){let n=this.database.query("SELECT id FROM projects WHERE id = ? AND organization_id = ?").get(t.id,e);return n?{organizationId:e,projectId:String(n.id)}:void 0}if(t.type==="environment"){let n=this.database.query("SELECT environments.id, environments.project_id FROM environments JOIN projects ON projects.id = environments.project_id WHERE environments.id = ? AND projects.organization_id = ?").get(t.id,e);return n?{organizationId:e,projectId:String(n.project_id),environmentId:String(n.id)}:void 0}let r=this.database.query(`SELECT resources.id, resources.project_id, resources.environment_id FROM resources
1485
1485
  JOIN projects ON projects.id = resources.project_id WHERE resources.id = ? AND projects.organization_id = ?`).get(t.id,e);return r?{organizationId:e,projectId:String(r.project_id),environmentId:S(r.environment_id),resourceId:String(r.id)}:void 0}createMembership(e){if(!this.getActor(e.actorId))throw Error("Membership actor was not found");let t=this.normalizeAuthorizationScope(e.organizationId,e.scope);if(e.roleTemplate==="owner"&&t.type!=="organization")throw Error("Owners must be scoped to the organization");let r=e.id??this.idFn(),n=this.now();f(this.database,`INSERT INTO organization_memberships (id, organization_id, actor_id, role_template, scope_type, scope_id, source, created_at, updated_at)
1486
1486
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[r,e.organizationId,e.actorId,e.roleTemplate,t.type,t.id??null,e.source??"manual",n,n]);let o=this.getMembership(r);return this.appendEvent({organizationId:e.organizationId,actorId:e.performedByActorId,type:"organization.membership.created",payload:{membershipId:r,actorId:e.actorId,roleTemplate:e.roleTemplate,scope:se(t)}}),o}getMembership(e){let t=this.database.query("SELECT * FROM organization_memberships WHERE id = ?").get(e);return t?Se(t):void 0}getMembershipForActor(e,t){let r=this.database.query("SELECT * FROM organization_memberships WHERE organization_id = ? AND actor_id = ?").get(e,t);return r?Se(r):void 0}listMemberships(e,t={}){let r=t.includeRevoked?"":"AND status = 'active'";return this.database.query(`SELECT * FROM organization_memberships WHERE organization_id = ? ${r} ORDER BY created_at, id`).all(e).map(Se)}updateMembership(e){let t=this.getMembership(e.id);if(!t)throw Error("Membership was not found");let r=this.normalizeAuthorizationScope(t.organizationId,e.scope??t.scope);if(e.roleTemplate==="owner"&&r.type!=="organization")throw Error("Owners must be scoped to the organization");if(t.roleTemplate==="owner"&&t.status==="active"&&(e.roleTemplate!=="owner"||r.type!=="organization"))this.assertAnotherOwner(t);return f(this.database,"UPDATE organization_memberships SET role_template = ?, scope_type = ?, scope_id = ?, session_version = session_version + 1, updated_at = ? WHERE id = ?",[e.roleTemplate,r.type,r.id??null,this.now(),t.id]),this.appendEvent({organizationId:t.organizationId,actorId:e.actorId,type:"organization.membership.updated",payload:{membershipId:t.id,from:{roleTemplate:t.roleTemplate,scope:se(t.scope)},to:{roleTemplate:e.roleTemplate,scope:se(r)}}}),this.getMembership(t.id)}revokeMembership(e,t){let r=this.getMembership(e);if(!r)throw Error("Membership was not found");if(r.status==="revoked")return r;if(r.roleTemplate==="owner")this.assertAnotherOwner(r);return f(this.database,"UPDATE organization_memberships SET status = 'revoked', session_version = session_version + 1, updated_at = ? WHERE id = ?",[this.now(),e]),this.appendEvent({organizationId:r.organizationId,actorId:t,type:"organization.membership.revoked",payload:{membershipId:e}}),this.getMembership(e)}touchMembership(e){let t=this.now();f(this.database,"UPDATE organization_memberships SET last_active_at = ?, updated_at = ? WHERE id = ? AND status = ?",[t,t,e,"active"]);let r=this.getMembership(e);if(!r)throw Error("Membership was not found");return r}assertAnotherOwner(e){if(Number(this.database.query("SELECT COUNT(*) AS count FROM organization_memberships WHERE organization_id = ? AND status = ? AND role_template = 'owner'").get(e.organizationId,"active")?.count??0)<=1)throw Error("Cannot remove or demote the last organization owner")}createInvitation(e){let t=e.email.trim().toLowerCase();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)||t.length>254)throw Error("A valid invitation email is required");let r=this.normalizeAuthorizationScope(e.organizationId,e.scope);if(e.roleTemplate==="owner"&&r.type!=="organization")throw Error("Owners must be scoped to the organization");let n=yr(32).toString("base64url"),o=_e("sha256").update(n).digest("hex"),a=e.id??this.idFn(),d=this.now(),u=new Date(this.nowFn().getTime()+Math.min(2592000000,Math.max(60000,e.expiresInMs??604800000))).toISOString();return f(this.database,`INSERT INTO organization_invitations (id, organization_id, email, role_template, scope_type, scope_id, token_hash, invited_by_actor_id, expires_at, created_at, updated_at)
1487
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[a,e.organizationId,t,e.roleTemplate,r.type,r.id??null,o,e.invitedByActorId??null,u,d,d]),this.appendEvent({organizationId:e.organizationId,actorId:e.invitedByActorId,type:"organization.invitation.created",payload:{invitationId:a,email:t,roleTemplate:e.roleTemplate,scope:se(r),expiresAt:u}}),{invitation:this.getInvitation(a),token:n}}getInvitation(e){let t=this.database.query("SELECT * FROM organization_invitations WHERE id = ?").get(e);return t?oe(t,this.now()):void 0}listInvitations(e){return this.database.query("SELECT * FROM organization_invitations WHERE organization_id = ? ORDER BY created_at DESC").all(e).map((t)=>oe(t,this.now()))}inspectInvitationToken(e){let t=_e("sha256").update(e).digest("hex"),r=this.database.query("SELECT * FROM organization_invitations WHERE token_hash = ?").get(t);return r?oe(r,this.now()):void 0}acceptInvitation(e,t){let r=_e("sha256").update(e).digest("hex");return this.transaction(()=>{let n=this.database.query("SELECT * FROM organization_invitations WHERE token_hash = ?").get(r);if(!n)throw Error("Invitation is invalid");let o=oe(n,this.now());if(o.state!=="pending")throw Error(`Invitation is ${o.state}`);if(!this.getActor(t))throw Error("Invitation actor was not found");if(f(this.database,"UPDATE organization_invitations SET accepted_by_actor_id = ?, accepted_at = ?, updated_at = ? WHERE id = ? AND accepted_at IS NULL AND revoked_at IS NULL AND expires_at > ?",[t,this.now(),this.now(),o.id,this.now()]).changes!==1)throw Error("Invitation is no longer available");let d=this.getMembershipForActor(o.organizationId,t),u=d??this.createMembership({organizationId:o.organizationId,actorId:t,roleTemplate:o.roleTemplate,scope:o.scope,source:"invitation"});if(d&&o.roleTemplate==="owner"&&d.roleTemplate!=="owner")u=this.updateMembership({id:d.id,roleTemplate:"owner",scope:{type:"organization"},actorId:t});else if(d)for(let p of nr(o.roleTemplate))this.upsertGrant({organizationId:o.organizationId,membershipId:d.id,effect:"allow",capability:p,scope:o.scope,source:"invitation"});return this.appendEvent({organizationId:o.organizationId,actorId:t,type:"organization.invitation.accepted",payload:{invitationId:o.id,membershipId:u.id}}),{invitation:this.getInvitation(o.id),membership:this.getMembership(u.id)}})}revokeInvitation(e,t){let r=this.getInvitation(e);if(!r)throw Error("Invitation was not found");if(r.acceptedAt)throw Error("Accepted invitations cannot be revoked");if(!r.revokedAt)f(this.database,"UPDATE organization_invitations SET revoked_at = ?, updated_at = ? WHERE id = ?",[this.now(),this.now(),e]);return this.appendEvent({organizationId:r.organizationId,actorId:t,type:"organization.invitation.revoked",payload:{invitationId:e}}),this.getInvitation(e)}reissueInvitation(e,t){let r=this.getInvitation(e);if(!r)throw Error("Invitation was not found");if(r.state==="accepted")throw Error("Accepted invitations cannot be reissued");return this.revokeInvitation(e,t),this.createInvitation({organizationId:r.organizationId,email:r.email,roleTemplate:r.roleTemplate,scope:r.scope,invitedByActorId:t})}upsertGrant(e){if(!be.includes(e.capability))throw Error("Unknown authorization capability");let t=this.getMembership(e.membershipId);if(!t||t.organizationId!==e.organizationId)throw Error("Grant membership was not found in this organization");let r=this.normalizeAuthorizationScope(e.organizationId,e.scope),n=this.now(),o=this.database.query("SELECT * FROM authorization_grants WHERE membership_id = ? AND effect = ? AND capability = ? AND scope_type = ? AND scope_id IS ?").get(e.membershipId,e.effect,e.capability,r.type,r.id??null);if(o)return Re(o);let a=e.id??this.idFn();return f(this.database,`INSERT INTO authorization_grants (id, organization_id, membership_id, effect, capability, scope_type, scope_id, source, created_at, updated_at)
1488
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[a,e.organizationId,e.membershipId,e.effect,e.capability,r.type,r.id??null,e.source??"manual",n,n]),f(this.database,"UPDATE organization_memberships SET session_version = session_version + 1, updated_at = ? WHERE id = ?",[n,e.membershipId]),this.appendEvent({organizationId:e.organizationId,actorId:e.actorId,type:"organization.grant.created",payload:{grantId:a,membershipId:e.membershipId,effect:e.effect,capability:e.capability,scope:se(r)}}),this.getGrant(a)}getGrant(e){let t=this.database.query("SELECT * FROM authorization_grants WHERE id = ?").get(e);return t?Re(t):void 0}listGrants(e){return this.database.query("SELECT * FROM authorization_grants WHERE membership_id = ? ORDER BY effect DESC, capability, scope_type, scope_id").all(e).map(Re)}removeGrant(e,t){let r=this.getGrant(e);if(!r)return!1;let n=f(this.database,"DELETE FROM authorization_grants WHERE id = ?",[e]).changes===1;if(n)f(this.database,"UPDATE organization_memberships SET session_version = session_version + 1, updated_at = ? WHERE id = ?",[this.now(),r.membershipId]),this.appendEvent({organizationId:r.organizationId,actorId:t,type:"organization.grant.removed",payload:{grantId:e,membershipId:r.membershipId}});return n}createOperation(e){if(e.idempotencyKey){let o=this.database.query("SELECT * FROM operations WHERE idempotency_key = ?").get(e.idempotencyKey);if(o)return K(o)}let t=e.id??this.idFn(),r=e.correlationId??this.idFn(),n=this.now();try{return this.transaction(()=>(f(this.database,`INSERT INTO operations (id, project_id, environment_id, resource_id, actor_id, kind, state, correlation_id, idempotency_key, input, output, priority, created_at, updated_at)
1487
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[a,e.organizationId,t,e.roleTemplate,r.type,r.id??null,o,e.invitedByActorId??null,u,d,d]),this.appendEvent({organizationId:e.organizationId,actorId:e.invitedByActorId,type:"organization.invitation.created",payload:{invitationId:a,email:t,roleTemplate:e.roleTemplate,scope:se(r),expiresAt:u}}),{invitation:this.getInvitation(a),token:n}}getInvitation(e){let t=this.database.query("SELECT * FROM organization_invitations WHERE id = ?").get(e);return t?oe(t,this.now()):void 0}listInvitations(e){return this.database.query("SELECT * FROM organization_invitations WHERE organization_id = ? ORDER BY created_at DESC").all(e).map((t)=>oe(t,this.now()))}inspectInvitationToken(e){let t=_e("sha256").update(e).digest("hex"),r=this.database.query("SELECT * FROM organization_invitations WHERE token_hash = ?").get(t);return r?oe(r,this.now()):void 0}acceptInvitation(e,t){let r=_e("sha256").update(e).digest("hex");return this.transaction(()=>{let n=this.database.query("SELECT * FROM organization_invitations WHERE token_hash = ?").get(r);if(!n)throw Error("Invitation is invalid");let o=oe(n,this.now());if(o.state!=="pending")throw Error(`Invitation is ${o.state}`);if(!this.getActor(t))throw Error("Invitation actor was not found");if(f(this.database,"UPDATE organization_invitations SET accepted_by_actor_id = ?, accepted_at = ?, updated_at = ? WHERE id = ? AND accepted_at IS NULL AND revoked_at IS NULL AND expires_at > ?",[t,this.now(),this.now(),o.id,this.now()]).changes!==1)throw Error("Invitation is no longer available");let d=this.getMembershipForActor(o.organizationId,t),u=d??this.createMembership({organizationId:o.organizationId,actorId:t,roleTemplate:o.roleTemplate,scope:o.scope,source:"invitation"});if(d&&o.roleTemplate==="owner"&&d.roleTemplate!=="owner")u=this.updateMembership({id:d.id,roleTemplate:"owner",scope:{type:"organization"},actorId:t});else if(d)for(let p of nr(o.roleTemplate))this.upsertGrant({organizationId:o.organizationId,membershipId:d.id,effect:"allow",capability:p,scope:o.scope,source:"invitation"});return this.appendEvent({organizationId:o.organizationId,actorId:t,type:"organization.invitation.accepted",payload:{invitationId:o.id,membershipId:u.id}}),{invitation:this.getInvitation(o.id),membership:this.getMembership(u.id)}})}revokeInvitation(e,t){let r=this.getInvitation(e);if(!r)throw Error("Invitation was not found");if(r.acceptedAt)throw Error("Accepted invitations cannot be revoked");if(!r.revokedAt)f(this.database,"UPDATE organization_invitations SET revoked_at = ?, updated_at = ? WHERE id = ?",[this.now(),this.now(),e]);return this.appendEvent({organizationId:r.organizationId,actorId:t,type:"organization.invitation.revoked",payload:{invitationId:e}}),this.getInvitation(e)}reissueInvitation(e,t){let r=this.getInvitation(e);if(!r)throw Error("Invitation was not found");if(r.state==="accepted")throw Error("Accepted invitations cannot be reissued");return this.revokeInvitation(e,t),this.createInvitation({organizationId:r.organizationId,email:r.email,roleTemplate:r.roleTemplate,scope:r.scope,invitedByActorId:t})}upsertGrant(e){if(!Ce.includes(e.capability))throw Error("Unknown authorization capability");let t=this.getMembership(e.membershipId);if(!t||t.organizationId!==e.organizationId)throw Error("Grant membership was not found in this organization");let r=this.normalizeAuthorizationScope(e.organizationId,e.scope),n=this.now(),o=this.database.query("SELECT * FROM authorization_grants WHERE membership_id = ? AND effect = ? AND capability = ? AND scope_type = ? AND scope_id IS ?").get(e.membershipId,e.effect,e.capability,r.type,r.id??null);if(o)return be(o);let a=e.id??this.idFn();return f(this.database,`INSERT INTO authorization_grants (id, organization_id, membership_id, effect, capability, scope_type, scope_id, source, created_at, updated_at)
1488
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[a,e.organizationId,e.membershipId,e.effect,e.capability,r.type,r.id??null,e.source??"manual",n,n]),f(this.database,"UPDATE organization_memberships SET session_version = session_version + 1, updated_at = ? WHERE id = ?",[n,e.membershipId]),this.appendEvent({organizationId:e.organizationId,actorId:e.actorId,type:"organization.grant.created",payload:{grantId:a,membershipId:e.membershipId,effect:e.effect,capability:e.capability,scope:se(r)}}),this.getGrant(a)}getGrant(e){let t=this.database.query("SELECT * FROM authorization_grants WHERE id = ?").get(e);return t?be(t):void 0}listGrants(e){return this.database.query("SELECT * FROM authorization_grants WHERE membership_id = ? ORDER BY effect DESC, capability, scope_type, scope_id").all(e).map(be)}removeGrant(e,t){let r=this.getGrant(e);if(!r)return!1;let n=f(this.database,"DELETE FROM authorization_grants WHERE id = ?",[e]).changes===1;if(n)f(this.database,"UPDATE organization_memberships SET session_version = session_version + 1, updated_at = ? WHERE id = ?",[this.now(),r.membershipId]),this.appendEvent({organizationId:r.organizationId,actorId:t,type:"organization.grant.removed",payload:{grantId:e,membershipId:r.membershipId}});return n}createOperation(e){if(e.idempotencyKey){let o=this.database.query("SELECT * FROM operations WHERE idempotency_key = ?").get(e.idempotencyKey);if(o)return K(o)}let t=e.id??this.idFn(),r=e.correlationId??this.idFn(),n=this.now();try{return this.transaction(()=>(f(this.database,`INSERT INTO operations (id, project_id, environment_id, resource_id, actor_id, kind, state, correlation_id, idempotency_key, input, output, priority, created_at, updated_at)
1489
1489
  VALUES (?, ?, ?, ?, ?, ?, 'queued', ?, ?, ?, '{}', ?, ?, ?)`,[t,e.projectId??null,e.environmentId??null,e.resourceId??null,e.actorId??null,e.kind,r,e.idempotencyKey??null,b(e.input??{}),e.priority??0,n,n]),this.appendEvent({projectId:e.projectId,operationId:t,resourceId:e.resourceId,actorId:e.actorId,correlationId:r,type:"operation.queued",payload:{kind:e.kind}}),this.getOperation(t)))}catch(o){if(e.idempotencyKey){let a=this.database.query("SELECT * FROM operations WHERE idempotency_key = ?").get(e.idempotencyKey);if(a)return K(a)}throw o}}getOperation(e){let t=this.database.query("SELECT * FROM operations WHERE id = ?").get(e);return t?K(t):void 0}listOperations(e={}){let t=[],r=[];if(e.projectId)t.push("project_id = ?"),r.push(e.projectId);if(e.state)t.push("state = ?"),r.push(e.state);if(e.kind)t.push("kind = ?"),r.push(e.kind);if(e.before)t.push("created_at < ?"),r.push(e.before);let n=Math.min(500,Math.max(1,e.limit??100));r.push(n);let o=t.length?`WHERE ${t.join(" AND ")}`:"";return this.database.query(`SELECT * FROM operations ${o} ORDER BY created_at DESC, id DESC LIMIT ?`).all(...r).map(K)}claimNextOperation(e,t=60000,r){let n=this.now(),o=new Date(this.nowFn().getTime()+t).toISOString();return this.transaction(()=>{let a=r?.length?`AND kind IN (${Cr(r.length)})`:"",d=r?[...r]:[],u=this.database.query(`SELECT * FROM operations WHERE state = 'queued' ${a} ORDER BY priority DESC, created_at ASC, id ASC LIMIT 1`).get(...d);if(!u)return;let p=K(u);if(f(this.database,`UPDATE operations SET state = 'running', attempt = attempt + 1, lease_owner = ?, lease_expires_at = ?,
1490
1490
  started_at = COALESCE(started_at, ?), updated_at = ?, version = version + 1 WHERE id = ? AND state = 'queued' AND version = ?`,[e,o,n,n,p.id,p.version]).changes!==1)return;return this.appendEvent({projectId:p.projectId,operationId:p.id,resourceId:p.resourceId,actorId:p.actorId,correlationId:p.correlationId,type:"operation.running",payload:{attempt:p.attempt+1,workerId:e}}),this.getOperation(p.id)})}claimOperation(e,t,r=60000){let n=this.now(),o=new Date(this.nowFn().getTime()+r).toISOString();return this.transaction(()=>{let a=this.getOperation(e);if(!a||a.state!=="queued")return;if(f(this.database,`UPDATE operations SET state = 'running', attempt = attempt + 1, lease_owner = ?, lease_expires_at = ?,
1491
1491
  started_at = COALESCE(started_at, ?), updated_at = ?, version = version + 1 WHERE id = ? AND state = 'queued' AND version = ?`,[t,o,n,n,a.id,a.version]).changes!==1)return;return this.appendEvent({projectId:a.projectId,operationId:a.id,resourceId:a.resourceId,actorId:a.actorId,correlationId:a.correlationId,type:"operation.running",payload:{attempt:a.attempt+1,workerId:t}}),this.getOperation(a.id)})}transitionOperation(e,t){return this.transaction(()=>{let r=this.getOperation(e);if(!r)throw Error(`Operation ${e} was not found`);let n=t.expectedVersion??r.version;if(r.version!==n)throw new wt("Operation",e,n);if(!br[r.state].includes(t.to))throw new Id(r.state,t.to);let o=this.now(),a=Sr.includes(t.to),d=t.to==="queued";if(f(this.database,`UPDATE operations SET state = ?, output = ?, error = ?, lease_owner = ?, lease_expires_at = ?,
@@ -1494,7 +1494,7 @@ import{Q,l}from"./chunk-q61qcpp4.js";import{cn}from"./chunk-84z2a1xn.js";var Je=
1494
1494
  ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`,[e,b(t),this.now()])}getSetting(e){let t=this.database.query("SELECT value FROM settings WHERE key = ?").get(e);return t?F(t.value):void 0}upsertTag(e,t,r="#5a8be0"){let n=t.trim().toLowerCase().replace(/\s+/g,"-");if(!/^[a-z0-9][a-z0-9-]{0,31}$/.test(n))throw Error("Tag names must contain 1-32 letters, numbers, or dashes");if(!/^#[0-9a-f]{6}$/i.test(r))throw Error("Tag colors must be six-digit hex colors");let o=this.now(),a=this.database.query("SELECT * FROM tags WHERE project_id = ? AND normalized_name = ?").get(e,n);if(a)return f(this.database,"UPDATE tags SET name = ?, color = ?, updated_at = ? WHERE id = ?",[t.trim(),r.toLowerCase(),o,String(a.id)]),ie(this.database.query("SELECT * FROM tags WHERE id = ?").get(String(a.id)));let d=this.idFn();return f(this.database,"INSERT INTO tags (id, project_id, name, normalized_name, color, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[d,e,t.trim(),n,r.toLowerCase(),o,o]),ie(this.database.query("SELECT * FROM tags WHERE id = ?").get(d))}listTags(e){return this.database.query("SELECT * FROM tags WHERE project_id = ? ORDER BY normalized_name").all(e).map(ie)}assignTag(e,t){if(!this.database.query("SELECT tags.id FROM tags JOIN resources ON resources.project_id = tags.project_id WHERE tags.id = ? AND resources.id = ?").get(t,e))throw Error("The tag and resource must belong to the same project");f(this.database,"INSERT OR IGNORE INTO resource_tags (resource_id, tag_id, created_at) VALUES (?, ?, ?)",[e,t,this.now()])}removeTag(e,t){f(this.database,"DELETE FROM resource_tags WHERE resource_id = ? AND tag_id = ?",[e,t])}listResourceTags(e){return this.database.query(`SELECT resource_tags.resource_id, tags.* FROM resource_tags JOIN tags ON tags.id = resource_tags.tag_id
1495
1495
  WHERE tags.project_id = ? ORDER BY tags.normalized_name`).all(e).map((r)=>({resourceId:String(r.resource_id),tag:ie(r)}))}saveFilter(e,t,r,n){let o=t.trim();if(!o||o.length>64)throw Error("Saved filter names must contain 1-64 characters");if(!r||r.length>160||/^[a-z][a-z0-9+.-]*:|^\/\//i.test(r))throw Error("Saved filter routes must be local route IDs or paths");let a=b(n);if(a.length>8192)throw Error("Saved filter queries must be smaller than 8 KB");let d=this.database.query("SELECT * FROM saved_filters WHERE actor_key = ? AND name = ?").get(e,o),u=this.now();if(d)return f(this.database,"UPDATE saved_filters SET route_id = ?, query = ?, updated_at = ? WHERE id = ?",[r,a,u,String(d.id)]),Le(this.database.query("SELECT * FROM saved_filters WHERE id = ?").get(String(d.id)));let p=this.idFn();return f(this.database,"INSERT INTO saved_filters (id, actor_key, name, route_id, query, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[p,e,o,r,a,u,u]),Le(this.database.query("SELECT * FROM saved_filters WHERE id = ?").get(p))}listSavedFilters(e){return this.database.query("SELECT * FROM saved_filters WHERE actor_key = ? ORDER BY updated_at DESC, name").all(e).map(Le)}deleteSavedFilter(e,t){return f(this.database,"DELETE FROM saved_filters WHERE actor_key = ? AND id = ?",[e,t]).changes===1}recordNavigation(e,t,r){let n=this.now();return f(this.database,`INSERT INTO navigation_items (actor_key, entity_type, entity_id, last_visited_at) VALUES (?, ?, ?, ?)
1496
1496
  ON CONFLICT(actor_key, entity_type, entity_id) DO UPDATE SET last_visited_at = excluded.last_visited_at, visit_count = visit_count + 1`,[e,t,r,n]),ve(this.database.query("SELECT * FROM navigation_items WHERE actor_key = ? AND entity_type = ? AND entity_id = ?").get(e,t,r))}setFavorite(e,t,r,n){let o=this.now();return f(this.database,`INSERT INTO navigation_items (actor_key, entity_type, entity_id, favorite, last_visited_at) VALUES (?, ?, ?, ?, ?)
1497
- ON CONFLICT(actor_key, entity_type, entity_id) DO UPDATE SET favorite = excluded.favorite`,[e,t,r,n?1:0,o]),ve(this.database.query("SELECT * FROM navigation_items WHERE actor_key = ? AND entity_type = ? AND entity_id = ?").get(e,t,r))}listNavigation(e,t={}){let r=t.favoritesOnly?"AND favorite = 1":"",n=Math.min(100,Math.max(1,t.limit??20));return this.database.query(`SELECT * FROM navigation_items WHERE actor_key = ? ${r} ORDER BY favorite DESC, last_visited_at DESC LIMIT ?`).all(e,n).map(ve)}compact(e={}){let t=new Date(this.nowFn().getTime()-(e.eventRetentionDays??90)*86400000).toISOString(),r=new Date(this.nowFn().getTime()-(e.operationRetentionDays??365)*86400000).toISOString(),n=this.transaction(()=>{let o=f(this.database,"DELETE FROM events WHERE created_at < ?",[t]).changes,a=f(this.database,"DELETE FROM operations WHERE created_at < ? AND state IN ('succeeded', 'failed', 'cancelled', 'timed_out')",[r]).changes;return{events:o,operations:a}});if(e.vacuum!==!1)this.database.run("VACUUM");return{deletedEvents:n.events,deletedOperations:n.operations,vacuumed:e.vacuum!==!1}}createBackup(e="manual"){if(this.path===":memory:")throw Error("Cannot create a filesystem backup for an in-memory control plane");let t=`${this.path}.${Date.now()}.bak`;return this.backupTo(t),this.setSetting("storage.last_backup",{path:t,createdAt:this.now(),reason:e}),t}integrityCheck(){let e=this.database.query("PRAGMA integrity_check").all();return e.length===1&&Object.values(e[0])[0]==="ok"?"ok":"corrupt"}health(){let e=Object.fromEntries(["queued","running","succeeded","failed","cancelled","timed_out"].map((o)=>[o,0]));for(let o of this.database.query("SELECT state, COUNT(*) AS count FROM operations GROUP BY state").all())e[String(o.state)]=Number(o.count);let t=this.database.query("PRAGMA journal_mode").get(),r=this.getSetting("storage.last_backup"),n=r&&!Array.isArray(r)&&typeof r==="object"&&typeof r.createdAt==="string"?r.createdAt:void 0;return{path:this.path,schemaVersion:Number(this.database.query("PRAGMA user_version").get()?.user_version??0),supportedSchemaVersion:Je,integrity:this.integrityCheck(),journalMode:String(t?.journal_mode??"unknown"),databaseBytes:this.path!==":memory:"&&_t(this.path)?vr(this.path).size:this.database.serialize().byteLength,lastBackupAt:n,operations:e,pendingRetryableOperations:e.queued+e.failed+e.timed_out}}exportSnapshot(){let e={};for(let t of this.database.query("SELECT key, value FROM settings ORDER BY key").all())e[String(t.key)]=F(t.value);return{format:"ts-cloud-control-plane",schemaVersion:Je,exportedAt:this.now(),organizations:this.database.query("SELECT * FROM organizations ORDER BY id").all().map(Ie),memberships:this.database.query("SELECT * FROM organization_memberships ORDER BY id").all().map(Se),invitations:this.database.query("SELECT * FROM organization_invitations ORDER BY id").all().map((t)=>({...oe(t,this.now()),tokenHash:String(t.token_hash)})),grants:this.database.query("SELECT * FROM authorization_grants ORDER BY id").all().map(Re),projects:this.database.query("SELECT * FROM projects ORDER BY id").all().map(he),environments:this.database.query("SELECT * FROM environments ORDER BY id").all().map(Ne),resources:this.database.query("SELECT * FROM resources ORDER BY id").all().map(fe),actors:this.database.query("SELECT * FROM actors ORDER BY id").all().map(ye),operations:this.database.query("SELECT * FROM operations ORDER BY id").all().map(K),events:this.database.query("SELECT * FROM events ORDER BY sequence").all().map(Ve),settings:e,tags:this.database.query("SELECT * FROM tags ORDER BY id").all().map(ie),resourceTags:this.database.query("SELECT * FROM resource_tags ORDER BY resource_id, tag_id").all().map((t)=>({resourceId:String(t.resource_id),tagId:String(t.tag_id),createdAt:String(t.created_at)})),savedFilters:this.database.query("SELECT * FROM saved_filters ORDER BY id").all().map(Le),navigationItems:this.database.query("SELECT * FROM navigation_items ORDER BY actor_key, entity_type, entity_id").all().map(ve)}}importSnapshot(e,t={}){if(e.format!=="ts-cloud-control-plane")throw Error("Unsupported control-plane snapshot format");if(e.schemaVersion>Je)throw new yo(e.schemaVersion,Je);this.transaction(()=>{if((Number(this.database.query("SELECT COUNT(*) AS count FROM projects").get()?.count??0)>0||Number(this.database.query("SELECT COUNT(*) AS count FROM operations").get()?.count??0)>0)&&!t.replace)throw Error("Control plane is not empty; pass replace: true to import this snapshot");if(t.replace)this.database.run("DELETE FROM authorization_grants"),this.database.run("DELETE FROM organization_invitations"),this.database.run("DELETE FROM organization_memberships"),this.database.run("DELETE FROM resource_tags"),this.database.run("DELETE FROM tags"),this.database.run("DELETE FROM saved_filters"),this.database.run("DELETE FROM navigation_items"),this.database.run("DELETE FROM events"),this.database.run("DELETE FROM operations"),this.database.run("DELETE FROM resources"),this.database.run("DELETE FROM environments"),this.database.run("DELETE FROM projects"),this.database.run("DELETE FROM actors"),this.database.run("DELETE FROM organizations"),this.database.run("DELETE FROM settings");for(let n of e.organizations??[])f(this.database,"INSERT INTO organizations (id, slug, name, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",[n.id,n.slug,n.name,n.createdAt,n.updatedAt]);for(let n of e.projects)f(this.database,`INSERT INTO projects (id, slug, name, description, organization_id, desired_config_hash, version, created_at, updated_at)
1497
+ ON CONFLICT(actor_key, entity_type, entity_id) DO UPDATE SET favorite = excluded.favorite`,[e,t,r,n?1:0,o]),ve(this.database.query("SELECT * FROM navigation_items WHERE actor_key = ? AND entity_type = ? AND entity_id = ?").get(e,t,r))}listNavigation(e,t={}){let r=t.favoritesOnly?"AND favorite = 1":"",n=Math.min(100,Math.max(1,t.limit??20));return this.database.query(`SELECT * FROM navigation_items WHERE actor_key = ? ${r} ORDER BY favorite DESC, last_visited_at DESC LIMIT ?`).all(e,n).map(ve)}compact(e={}){let t=new Date(this.nowFn().getTime()-(e.eventRetentionDays??90)*86400000).toISOString(),r=new Date(this.nowFn().getTime()-(e.operationRetentionDays??365)*86400000).toISOString(),n=this.transaction(()=>{let o=f(this.database,"DELETE FROM events WHERE created_at < ?",[t]).changes,a=f(this.database,"DELETE FROM operations WHERE created_at < ? AND state IN ('succeeded', 'failed', 'cancelled', 'timed_out')",[r]).changes;return{events:o,operations:a}});if(e.vacuum!==!1)this.database.run("VACUUM");return{deletedEvents:n.events,deletedOperations:n.operations,vacuumed:e.vacuum!==!1}}createBackup(e="manual"){if(this.path===":memory:")throw Error("Cannot create a filesystem backup for an in-memory control plane");let t=`${this.path}.${Date.now()}.bak`;return this.backupTo(t),this.setSetting("storage.last_backup",{path:t,createdAt:this.now(),reason:e}),t}integrityCheck(){let e=this.database.query("PRAGMA integrity_check").all();return e.length===1&&Object.values(e[0])[0]==="ok"?"ok":"corrupt"}health(){let e=Object.fromEntries(["queued","running","succeeded","failed","cancelled","timed_out"].map((o)=>[o,0]));for(let o of this.database.query("SELECT state, COUNT(*) AS count FROM operations GROUP BY state").all())e[String(o.state)]=Number(o.count);let t=this.database.query("PRAGMA journal_mode").get(),r=this.getSetting("storage.last_backup"),n=r&&!Array.isArray(r)&&typeof r==="object"&&typeof r.createdAt==="string"?r.createdAt:void 0;return{path:this.path,schemaVersion:Number(this.database.query("PRAGMA user_version").get()?.user_version??0),supportedSchemaVersion:Je,integrity:this.integrityCheck(),journalMode:String(t?.journal_mode??"unknown"),databaseBytes:this.path!==":memory:"&&_t(this.path)?vr(this.path).size:this.database.serialize().byteLength,lastBackupAt:n,operations:e,pendingRetryableOperations:e.queued+e.failed+e.timed_out}}exportSnapshot(){let e={};for(let t of this.database.query("SELECT key, value FROM settings ORDER BY key").all())e[String(t.key)]=F(t.value);return{format:"ts-cloud-control-plane",schemaVersion:Je,exportedAt:this.now(),organizations:this.database.query("SELECT * FROM organizations ORDER BY id").all().map(Ie),memberships:this.database.query("SELECT * FROM organization_memberships ORDER BY id").all().map(Se),invitations:this.database.query("SELECT * FROM organization_invitations ORDER BY id").all().map((t)=>({...oe(t,this.now()),tokenHash:String(t.token_hash)})),grants:this.database.query("SELECT * FROM authorization_grants ORDER BY id").all().map(be),projects:this.database.query("SELECT * FROM projects ORDER BY id").all().map(he),environments:this.database.query("SELECT * FROM environments ORDER BY id").all().map(Ne),resources:this.database.query("SELECT * FROM resources ORDER BY id").all().map(fe),actors:this.database.query("SELECT * FROM actors ORDER BY id").all().map(ye),operations:this.database.query("SELECT * FROM operations ORDER BY id").all().map(K),events:this.database.query("SELECT * FROM events ORDER BY sequence").all().map(Ve),settings:e,tags:this.database.query("SELECT * FROM tags ORDER BY id").all().map(ie),resourceTags:this.database.query("SELECT * FROM resource_tags ORDER BY resource_id, tag_id").all().map((t)=>({resourceId:String(t.resource_id),tagId:String(t.tag_id),createdAt:String(t.created_at)})),savedFilters:this.database.query("SELECT * FROM saved_filters ORDER BY id").all().map(Le),navigationItems:this.database.query("SELECT * FROM navigation_items ORDER BY actor_key, entity_type, entity_id").all().map(ve)}}importSnapshot(e,t={}){if(e.format!=="ts-cloud-control-plane")throw Error("Unsupported control-plane snapshot format");if(e.schemaVersion>Je)throw new yo(e.schemaVersion,Je);this.transaction(()=>{if((Number(this.database.query("SELECT COUNT(*) AS count FROM projects").get()?.count??0)>0||Number(this.database.query("SELECT COUNT(*) AS count FROM operations").get()?.count??0)>0)&&!t.replace)throw Error("Control plane is not empty; pass replace: true to import this snapshot");if(t.replace)this.database.run("DELETE FROM authorization_grants"),this.database.run("DELETE FROM organization_invitations"),this.database.run("DELETE FROM organization_memberships"),this.database.run("DELETE FROM resource_tags"),this.database.run("DELETE FROM tags"),this.database.run("DELETE FROM saved_filters"),this.database.run("DELETE FROM navigation_items"),this.database.run("DELETE FROM events"),this.database.run("DELETE FROM operations"),this.database.run("DELETE FROM resources"),this.database.run("DELETE FROM environments"),this.database.run("DELETE FROM projects"),this.database.run("DELETE FROM actors"),this.database.run("DELETE FROM organizations"),this.database.run("DELETE FROM settings");for(let n of e.organizations??[])f(this.database,"INSERT INTO organizations (id, slug, name, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",[n.id,n.slug,n.name,n.createdAt,n.updatedAt]);for(let n of e.projects)f(this.database,`INSERT INTO projects (id, slug, name, description, organization_id, desired_config_hash, version, created_at, updated_at)
1498
1498
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.id,n.slug,n.name,n.description??null,n.organizationId??null,n.desiredConfigHash??null,n.version,n.createdAt,n.updatedAt]);for(let n of e.environments)f(this.database,`INSERT INTO environments (id, project_id, slug, name, kind, region, desired_state, discovered_state, version, created_at, updated_at)
1499
1499
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.id,n.projectId,n.slug,n.name,n.kind,n.region??null,b(n.desiredState),b(n.discoveredState),n.version,n.createdAt,n.updatedAt]);for(let n of e.resources)f(this.database,`INSERT INTO resources (id, project_id, environment_id, kind, slug, name, provider, provider_id, desired_state, discovered_state, metadata, version, created_at, updated_at)
1500
1500
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.id,n.projectId,n.environmentId??null,n.kind,n.slug,n.name,n.provider??null,n.providerId??null,b(n.desiredState),b(n.discoveredState),b(n.metadata),n.version,n.createdAt,n.updatedAt]);for(let n of e.actors)f(this.database,`INSERT INTO actors (id, kind, external_id, display_name, metadata, disabled_at, version, created_at, updated_at)
@@ -1504,7 +1504,7 @@ import{Q,l}from"./chunk-q61qcpp4.js";import{cn}from"./chunk-84z2a1xn.js";var Je=
1504
1504
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.id,n.organizationId,n.membershipId,n.effect,n.capability,n.scope.type,n.scope.id??null,n.source??"manual",n.createdAt,n.updatedAt]);for(let n of e.operations)f(this.database,`INSERT INTO operations (id, project_id, environment_id, resource_id, actor_id, kind, state, correlation_id, idempotency_key,
1505
1505
  input, output, error, attempt, priority, lease_owner, lease_expires_at, cancel_requested_at, started_at, finished_at, version, created_at, updated_at)
1506
1506
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.id,n.projectId??null,n.environmentId??null,n.resourceId??null,n.actorId??null,n.kind,n.state,n.correlationId,n.idempotencyKey??null,b(n.input),b(n.output),Be(n.error)??null,n.attempt,n.priority,n.leaseOwner??null,n.leaseExpiresAt??null,n.cancelRequestedAt??null,n.startedAt??null,n.finishedAt??null,n.version,n.createdAt,n.updatedAt]);for(let n of e.events)f(this.database,`INSERT INTO events (sequence, id, organization_id, project_id, operation_id, resource_id, actor_id, correlation_id, type, level, payload, created_at)
1507
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.sequence,n.id,n.organizationId??null,n.projectId??null,n.operationId??null,n.resourceId??null,n.actorId??null,n.correlationId,n.type,n.level,b(n.payload),n.createdAt]);for(let[n,o]of Object.entries(e.settings))f(this.database,"INSERT INTO settings (key, value, updated_at) VALUES (?, ?, ?)",[n,b(o),this.now()]);for(let n of e.tags??[])f(this.database,"INSERT INTO tags (id, project_id, name, normalized_name, color, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[n.id,n.projectId,n.name,n.normalizedName,n.color,n.createdAt,n.updatedAt]);for(let n of e.resourceTags??[])f(this.database,"INSERT INTO resource_tags (resource_id, tag_id, created_at) VALUES (?, ?, ?)",[n.resourceId,n.tagId,n.createdAt]);for(let n of e.savedFilters??[])f(this.database,"INSERT INTO saved_filters (id, actor_key, name, route_id, query, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[n.id,n.actorKey,n.name,n.routeId,b(n.query),n.createdAt,n.updatedAt]);for(let n of e.navigationItems??[])f(this.database,"INSERT INTO navigation_items (actor_key, entity_type, entity_id, favorite, last_visited_at, visit_count) VALUES (?, ?, ?, ?, ?, ?)",[n.actorKey,n.entityType,n.entityId,n.favorite?1:0,n.lastVisitedAt,n.visitCount])})}}var Ar=new Set(["domain","domains","hostname","hostnames","url","repository","repo","image","label","labels"]),Or=new Set(["sha","commit","commitsha","release","releaseid"]);function ft(e,t){if(!e||typeof e!=="object"||Array.isArray(e))return[];let r=[];for(let[n,o]of Object.entries(e)){if(!t.has(n.toLowerCase()))continue;if(typeof o==="string")r.push(o);else if(Array.isArray(o))r.push(...o.filter((a)=>typeof a==="string"))}return r}function Qe(e){return e.toLowerCase().trim().replace(/[^a-z0-9._:/@-]+/g," ")}function Ge(e,t,r){let n=Qe(e),o=Qe(t),a=Qe(r);if(!n)return 0;if(o===n)return 1000;if(o.startsWith(n))return 800-Math.min(100,o.length-n.length);if(o.includes(n))return 650-Math.min(100,o.indexOf(n));let d=n.split(/\s+/).filter(Boolean);if(d.every((p)=>a.includes(p)))return 400+d.length*10;let u=0;for(let p of n){if(u=a.indexOf(p,u),u<0)return 0;u++}return Math.max(1,180-Math.floor(a.length/20))}function Ur(e,t){let r=e.kind.toLowerCase();if(r==="server"||r==="compute")return{type:"server",href:`/server/metrics?env=${encodeURIComponent(t)}`};if(r.includes("database")||["mysql","postgres","postgresql","sqlite","redis"].includes(r))return{type:"database",href:`/server/database?env=${encodeURIComponent(t)}&database=${encodeURIComponent(e.slug)}`};return{type:"service",href:`/server/sites?env=${encodeURIComponent(t)}&service=${encodeURIComponent(e.slug)}`}}function So(e,t){let r=e.getProject(t.projectId);if(!r)return[];let n=e.listEnvironments(r.id),o=new Map(n.map((m)=>[m.id,m])),a=e.listResourceTags(r.id),d=new Map;for(let m of a){let T=d.get(m.resourceId)??[];T.push({id:m.tag.id,name:m.tag.name,color:m.tag.color}),d.set(m.resourceId,T)}let u=[],p=t.allowedResourceSlugs!==void 0;if(!p){u.push({type:"project",id:r.id,title:r.name,subtitle:r.slug,href:`/?project=${encodeURIComponent(r.slug)}`,tags:[],score:0});for(let m of n)u.push({type:"environment",id:m.id,title:m.name,subtitle:`${r.name} · ${m.kind}`,href:`/?env=${encodeURIComponent(m.slug)}`,environment:m.slug,tags:[],score:0})}let E=e.listResources(r.id).filter((m)=>!t.allowedResourceSlugs||t.allowedResourceSlugs.has(m.slug));for(let m of E){let T=m.environmentId?o.get(m.environmentId):void 0,h=d.get(m.id)??[],_=ft(m.desiredState,Ar),N=[m.name,m.slug,m.kind,m.provider,m.providerId,T?.slug,..._,...h.map((L)=>L.name)].filter(Boolean).join(" "),y=Ur(m,T?.slug??n[0]?.slug??"");u.push({type:y.type,id:m.id,title:m.name,subtitle:[m.kind,..._.slice(0,2)].join(" · "),href:y.href,environment:T?.slug,provider:m.provider,tags:h,score:Ge(t.query,m.name,N)})}if(!p)for(let m of e.listOperations({projectId:r.id,limit:500})){let T=m.environmentId?o.get(m.environmentId):void 0,h=ft(m.input,Or),_=m.kind.includes("deploy"),N=h[0]??m.kind,y=[m.kind,m.id,m.correlationId,m.state,...h].join(" ");u.push({type:_?"deployment":"operation",id:m.id,title:N,subtitle:`${m.kind} · ${m.state}`,href:`/server/activity?env=${encodeURIComponent(T?.slug??n[0]?.slug??"")}&operation=${encodeURIComponent(m.id)}`,environment:T?.slug,status:m.state,tags:[],score:Ge(t.query,N,y)})}for(let m of u)if(m.score===0)m.score=Ge(t.query,m.title,`${m.title} ${m.subtitle} ${m.environment??""} ${m.provider??""}`);let g={service:0,server:1,database:2,deployment:3,environment:4,project:5,operation:6};return u.filter((m)=>m.score>0).sort((m,T)=>T.score-m.score||g[m.type]-g[T.type]||m.title.localeCompare(T.title)||m.id.localeCompare(T.id)).slice(0,Math.min(50,Math.max(1,t.limit??20)))}import{createHash as Dr}from"node:crypto";var It=/^[a-z0-9](?:[a-z0-9_.-]{0,62})$/,wr=/^[A-Za-z_][A-Za-z0-9_]{0,127}$/,kr=/(?:secret|token|password|passwd|private.?key|api.?key|credential)/i,Pr=new Set(["image","build","command","entrypoint","environment","ports","volumes","networks","depends_on","healthcheck","restart","deploy","labels"]),yt=new Map([["privileged","Privileged containers are blocked."],["network_mode","Host/custom network modes are blocked."],["pid","Host PID namespaces are blocked."],["ipc","Host IPC namespaces are blocked."],["devices","Device access is blocked."],["cap_add","Additional Linux capabilities require an external policy exception."],["security_opt","Custom security options require an external policy exception."]]);function U(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function Ze(e){return Array.isArray(e)?e:e==null?[]:[e]}function xr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,63)||"compose-app"}function de(e){if(Array.isArray(e))return e.map(String);if(typeof e==="string"&&e.trim())return["sh","-c",e];return}function We(e,t){let r=String(e??""),n=/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(r);if(!n)return t;let o=Number(n[1]);return Math.max(0,Math.round(o*(n[2]==="ms"?0.001:n[2]==="m"?60:n[2]==="h"?3600:1)))}function Lt(e){let t=/^(\d+(?:\.\d+)?)\s*(b|k|kb|kib|m|mb|mib|g|gb|gib)?$/i.exec(String(e??""));if(!t)return;let r=Number(t[1]),n=String(t[2]??"b").toLowerCase(),o=r*(n.startsWith("g")?1073741824:n.startsWith("m")?1048576:n.startsWith("k")?1024:1);return Math.max(1,Math.round(o/1024/1024))}function jr(e){if(e==null)return"";return/^\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}$/.exec(String(e))?.[1]}function St(e,t,r){let n={},o=Array.isArray(e)?e.map((a)=>{let[d,...u]=String(a).split("=");return[d,u.length?u.join("="):null]}):Object.entries(U(e));for(let[a,d]of o){let u=String(a);if(!wr.test(u)){r.push({severity:"error",path:`${t}.${u}`,code:"environment.name",message:"Environment variable names must use portable shell identifiers."});continue}let p=jr(d);if(p!==void 0){n[u]={secretRef:p||u};continue}if(kr.test(u)){r.push({severity:"error",path:`${t}.${u}`,code:"secret.literal",message:"Literal secret-like environment values are not stored.",alternative:`Use \${${u}} and supply ${u} through the secret store.`}),n[u]={secretRef:u};continue}n[u]=String(d??"")}return n}function Fr(e,t,r){let n=[];for(let[o,a]of Ze(e).entries()){let d,u,p="tcp";if(typeof a==="number")d=a;else if(typeof a==="string"){let[E,g]=a.split("/");p=g==="udp"?"udp":"tcp";let m=E.split(":");d=Number(m.at(-1)),u=m.length>1?Number(m.at(-2)):void 0}else{let E=U(a);d=Number(E.target),u=E.published==null?void 0:Number(E.published),p=E.protocol==="udp"?"udp":"tcp"}if(!Number.isInteger(d)||d<1||d>65535||u!=null&&(!Number.isInteger(u)||u<1||u>65535))r.push({severity:"error",path:`${t}[${o}]`,code:"port.invalid",message:"Ports must be integers from 1 through 65535."});else n.push({target:d,...u?{published:u}:{},protocol:p})}return n}function Mr(e,t,r,n){let o=[];for(let[a,d]of Ze(e).entries()){let u="",p="",E=!1,g="volume";if(typeof d==="string"){let m=d.split(":");u=m[0]??"",p=m[1]??"",E=m.slice(2).includes("ro"),g=u.startsWith("/")||u.startsWith(".")?"bind":"volume"}else{let m=U(d);u=String(m.source??""),p=String(m.target??""),E=m.read_only===!0,g=String(m.type??"volume")}if(g!=="volume"||u.startsWith("/")||u.startsWith(".")){n.push({severity:"error",path:`${r}[${a}]`,code:"volume.host_mount",message:"Host and bind mounts are blocked; use a named volume.",alternative:"Declare the volume at the top level and mount it by name."});continue}if(!It.test(u)||!p.startsWith("/")){n.push({severity:"error",path:`${r}[${a}]`,code:"volume.invalid",message:"A named source and absolute container target are required."});continue}if(!t.has(u))n.push({severity:"warning",path:`${r}[${a}]`,code:"volume.implicit",message:`Named volume ${u} is implicit and will be declared on export.`});t.add(u),o.push({source:u,target:p,readOnly:E})}return o}function zr(e){return Array.isArray(e)?e.map((t)=>({service:String(t),condition:"service_started"})):Object.entries(U(e)).map(([t,r])=>({service:t,condition:["service_started","service_healthy","service_completed_successfully"].includes(String(U(r).condition))?String(U(r).condition):"service_started"}))}function vt(e){let t=U(e);if(!Object.keys(t).length||t.disable===!0)return;let r=de(t.test);return r?{test:r,intervalSeconds:We(t.interval,30),timeoutSeconds:We(t.timeout,5),retries:Math.max(1,Number(t.retries)||3),...t.start_period?{startPeriodSeconds:We(t.start_period,0)}:{}}:void 0}function qr(e,t,r){if(!e)return;let n=typeof e==="string"?{context:e}:U(e),o=String(n.context??"."),a=String(n.dockerfile??"Dockerfile");if(o.startsWith("/")||o.split("/").includes("..")||a.startsWith("/")||a.split("/").includes(".."))r.push({severity:"error",path:t,code:"build.traversal",message:"Build context and Dockerfile must stay inside the repository."});return{context:o,dockerfile:a,...n.target?{target:String(n.target)}:{},args:St(n.args,`${t}.args`,r)}}function Hr(e,t,r){let n=Array.isArray(e)?Object.fromEntries(e.map((a)=>String(a).split("=",2))):U(e),o=String(n["ts-cloud.domains"]??n["ts-cloud.domain"]??"").split(",").map((a)=>a.trim()).filter(Boolean);for(let a of o)if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(a))r.push({severity:"error",path:t,code:"domain.invalid",message:`Invalid service domain ${a}.`});return o.filter((a)=>/\./.test(a))}function Br(e,t){let r=[],n=new Set,o=new Set,a=(d)=>{if(o.has(d))return;if(n.has(d)){t.push({severity:"error",path:`services.${d}.depends_on`,code:"dependency.cycle",message:"Service dependencies contain a cycle."});return}n.add(d);for(let u of e[d]?.dependsOn??[])if(!e[u.service])t.push({severity:"error",path:`services.${d}.depends_on.${u.service}`,code:"dependency.missing",message:`Dependency ${u.service} does not exist.`});else a(u.service);n.delete(d),o.add(d),r.push(d)};return Object.keys(e).sort().forEach(a),r}function Wr(e,t){if(Buffer.byteLength(e)>524288)throw Error("Compose source exceeds the 512 KiB limit");let r;try{r=U(Bun.YAML.parse(e))}catch(T){throw Error(`Compose YAML could not be parsed: ${T instanceof Error?T.message:String(T)}`)}let n=[],o=U(r.services),a=Object.keys(o);if(!a.length)n.push({severity:"error",path:"services",code:"services.required",message:"At least one service is required."});if(a.length>64)n.push({severity:"error",path:"services",code:"services.limit",message:"A Compose application may contain at most 64 services."});let d=new Set(Object.keys(U(r.volumes))),u=new Set(Object.keys(U(r.networks))),p={};for(let T of a.sort()){let h=`services.${T}`,_=U(o[T]);if(!It.test(T)){n.push({severity:"error",path:h,code:"service.name",message:"Service names must be portable lowercase identifiers."});continue}for(let[A,Nr]of yt)if(_[A]!=null&&_[A]!==!1&&(!Array.isArray(_[A])||_[A].length))n.push({severity:"error",path:`${h}.${A}`,code:`unsafe.${A}`,message:Nr});for(let A of Object.keys(_))if(!Pr.has(A)&&!yt.has(A))n.push({severity:"warning",path:`${h}.${A}`,code:"field.unsupported",message:`Compose field ${A} is not in the supported subset and will not be deployed.`});let N=_.image?String(_.image):void 0,y=qr(_.build,`${h}.build`,n);if(!N&&!y)n.push({severity:"error",path:h,code:"service.source",message:"Each service requires image or build."});if(N&&!N.includes("@sha256:")&&(!N.includes(":")||N.endsWith(":latest")))n.push({severity:"warning",path:`${h}.image`,code:"image.floating",message:`Image ${N} is not pinned to a digest or explicit tag.`});let L=Ze(_.networks).map((A)=>typeof A==="string"?A:String(U(A).name??"")).filter(Boolean);L.forEach((A)=>u.add(A));let v=U(_.deploy),I=U(v.resources),C=U(I.limits),w=["no","always","on-failure","unless-stopped"].includes(String(_.restart))?String(_.restart):"unless-stopped";p[T]={name:T,...N?{image:N}:{},...y?{build:y}:{},...de(_.command)?{command:de(_.command)}:{},...de(_.entrypoint)?{entrypoint:de(_.entrypoint)}:{},environment:St(_.environment,`${h}.environment`,n),ports:Fr(_.ports,`${h}.ports`,n),volumes:Mr(_.volumes,d,`${h}.volumes`,n),networks:L,dependsOn:zr(_.depends_on),...vt(_.healthcheck)?{healthCheck:vt(_.healthcheck)}:{},restart:w,...Number(C.cpus)>0?{cpu:Number(C.cpus)}:{},...Lt(C.memory)?{memoryMb:Lt(C.memory)}:{},replicas:Math.max(1,Math.min(100,Number(v.replicas)||1)),domains:Hr(_.labels,`${h}.labels`,n)}}let E=Br(p,n),g={apiVersion:"ts-cloud.dev/v1",kind:"ComposeApplication",metadata:{name:t.name.trim(),slug:xr(t.slug??t.name),projectId:t.projectId,environmentId:t.environmentId},spec:{services:p,networks:[...u].sort(),volumes:[...d].sort(),dependencyOrder:E}},m=Cd(g);return{valid:!n.some((T)=>T.severity==="error"),manifest:g,diagnostics:n,redactedSource:m,sourceHash:Dr("sha256").update(e).digest("hex")}}function Cd(e){let t=Object.fromEntries(Object.entries(e.spec.services).map(([r,n])=>[r,{...n.image?{image:n.image}:{},...n.build?{build:{context:n.build.context,dockerfile:n.build.dockerfile,...n.build.target?{target:n.build.target}:{},...Object.keys(n.build.args).length?{args:Object.fromEntries(Object.entries(n.build.args).map(([o,a])=>[o,typeof a==="string"?a:`\${${a.secretRef}:?required secret ${a.secretRef}}`]))}:{}}}:{},...n.command?{command:n.command}:{},...n.entrypoint?{entrypoint:n.entrypoint}:{},...Object.keys(n.environment).length?{environment:Object.fromEntries(Object.entries(n.environment).map(([o,a])=>[o,typeof a==="string"?a:`\${${a.secretRef}:?required secret ${a.secretRef}}`]))}:{},...n.ports.length?{ports:n.ports.map((o)=>`${o.published?`${o.published}:`:""}${o.target}${o.protocol==="udp"?"/udp":""}`)}:{},...n.volumes.length?{volumes:n.volumes.map((o)=>`${o.source}:${o.target}${o.readOnly?":ro":""}`)}:{},...n.networks.length?{networks:n.networks}:{},...n.dependsOn.length?{depends_on:Object.fromEntries(n.dependsOn.map((o)=>[o.service,{condition:o.condition}]))}:{},...n.healthCheck?{healthcheck:{test:n.healthCheck.test,interval:`${n.healthCheck.intervalSeconds}s`,timeout:`${n.healthCheck.timeoutSeconds}s`,retries:n.healthCheck.retries,...n.healthCheck.startPeriodSeconds!=null?{start_period:`${n.healthCheck.startPeriodSeconds}s`}:{}}}:{},restart:n.restart,...n.cpu||n.memoryMb||n.replicas!==1?{deploy:{replicas:n.replicas,resources:{limits:{...n.cpu?{cpus:String(n.cpu)}:{},...n.memoryMb?{memory:`${n.memoryMb}M`}:{}}}}}:{},...n.domains.length?{labels:{"ts-cloud.domains":n.domains.join(",")}}:{}}]));return Bun.YAML.stringify({services:t,...e.spec.networks.length?{networks:Object.fromEntries(e.spec.networks.map((r)=>[r,{}]))}:{},...e.spec.volumes.length?{volumes:Object.fromEntries(e.spec.volumes.map((r)=>[r,{}]))}:{}})}function Ed(e,t){let r=[],n=(o,a,d)=>{if(JSON.stringify(a)===JSON.stringify(d))return;if(a&&d&&typeof a==="object"&&typeof d==="object"&&!Array.isArray(a)&&!Array.isArray(d)){for(let u of[...new Set([...Object.keys(a),...Object.keys(d)])].sort())n(o?`${o}.${u}`:u,a[u],d[u]);return}r.push({path:o,...a!==void 0?{before:a}:{},...d!==void 0?{after:d}:{}})};return n("",e,t),r}import{createHash as bt}from"node:crypto";var Vr="2026-07-21T00:00:00.000Z",Ct=[{id:"bun-postgres-redis",name:"Bun + Postgres + Redis",description:"Web and worker services with durable Postgres and Redis dependencies.",category:"application",version:"1.0.0",sourceVersion:"oven/bun:1.2.21,postgres:17.5,redis:8.0.3",architecture:"web → Postgres + Redis; worker → Postgres + Redis",minimumResources:{cpu:2,memoryMb:3072},exposedServices:["web"],maintenanceNotes:"Back up the Postgres volume before major upgrades.",inputs:[{name:"domain",label:"Web domain",required:!0,secret:!1}],source:`services:
1507
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[n.sequence,n.id,n.organizationId??null,n.projectId??null,n.operationId??null,n.resourceId??null,n.actorId??null,n.correlationId,n.type,n.level,b(n.payload),n.createdAt]);for(let[n,o]of Object.entries(e.settings))f(this.database,"INSERT INTO settings (key, value, updated_at) VALUES (?, ?, ?)",[n,b(o),this.now()]);for(let n of e.tags??[])f(this.database,"INSERT INTO tags (id, project_id, name, normalized_name, color, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[n.id,n.projectId,n.name,n.normalizedName,n.color,n.createdAt,n.updatedAt]);for(let n of e.resourceTags??[])f(this.database,"INSERT INTO resource_tags (resource_id, tag_id, created_at) VALUES (?, ?, ?)",[n.resourceId,n.tagId,n.createdAt]);for(let n of e.savedFilters??[])f(this.database,"INSERT INTO saved_filters (id, actor_key, name, route_id, query, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)",[n.id,n.actorKey,n.name,n.routeId,b(n.query),n.createdAt,n.updatedAt]);for(let n of e.navigationItems??[])f(this.database,"INSERT INTO navigation_items (actor_key, entity_type, entity_id, favorite, last_visited_at, visit_count) VALUES (?, ?, ?, ?, ?, ?)",[n.actorKey,n.entityType,n.entityId,n.favorite?1:0,n.lastVisitedAt,n.visitCount])})}}var Ar=new Set(["domain","domains","hostname","hostnames","url","repository","repo","image","label","labels"]),Or=new Set(["sha","commit","commitsha","release","releaseid"]);function ft(e,t){if(!e||typeof e!=="object"||Array.isArray(e))return[];let r=[];for(let[n,o]of Object.entries(e)){if(!t.has(n.toLowerCase()))continue;if(typeof o==="string")r.push(o);else if(Array.isArray(o))r.push(...o.filter((a)=>typeof a==="string"))}return r}function Qe(e){return e.toLowerCase().trim().replace(/[^a-z0-9._:/@-]+/g," ")}function Ge(e,t,r){let n=Qe(e),o=Qe(t),a=Qe(r);if(!n)return 0;if(o===n)return 1000;if(o.startsWith(n))return 800-Math.min(100,o.length-n.length);if(o.includes(n))return 650-Math.min(100,o.indexOf(n));let d=n.split(/\s+/).filter(Boolean);if(d.every((p)=>a.includes(p)))return 400+d.length*10;let u=0;for(let p of n){if(u=a.indexOf(p,u),u<0)return 0;u++}return Math.max(1,180-Math.floor(a.length/20))}function Ur(e,t){let r=e.kind.toLowerCase();if(r==="server"||r==="compute")return{type:"server",href:`/server/metrics?env=${encodeURIComponent(t)}`};if(r.includes("database")||["mysql","postgres","postgresql","sqlite","redis"].includes(r))return{type:"database",href:`/server/database?env=${encodeURIComponent(t)}&database=${encodeURIComponent(e.slug)}`};return{type:"service",href:`/server/sites?env=${encodeURIComponent(t)}&service=${encodeURIComponent(e.slug)}`}}function So(e,t){let r=e.getProject(t.projectId);if(!r)return[];let n=e.listEnvironments(r.id),o=new Map(n.map((m)=>[m.id,m])),a=e.listResourceTags(r.id),d=new Map;for(let m of a){let T=d.get(m.resourceId)??[];T.push({id:m.tag.id,name:m.tag.name,color:m.tag.color}),d.set(m.resourceId,T)}let u=[],p=t.allowedResourceSlugs!==void 0;if(!p){u.push({type:"project",id:r.id,title:r.name,subtitle:r.slug,href:`/?project=${encodeURIComponent(r.slug)}`,tags:[],score:0});for(let m of n)u.push({type:"environment",id:m.id,title:m.name,subtitle:`${r.name} · ${m.kind}`,href:`/?env=${encodeURIComponent(m.slug)}`,environment:m.slug,tags:[],score:0})}let E=e.listResources(r.id).filter((m)=>!t.allowedResourceSlugs||t.allowedResourceSlugs.has(m.slug));for(let m of E){let T=m.environmentId?o.get(m.environmentId):void 0,h=d.get(m.id)??[],_=ft(m.desiredState,Ar),N=[m.name,m.slug,m.kind,m.provider,m.providerId,T?.slug,..._,...h.map((L)=>L.name)].filter(Boolean).join(" "),y=Ur(m,T?.slug??n[0]?.slug??"");u.push({type:y.type,id:m.id,title:m.name,subtitle:[m.kind,..._.slice(0,2)].join(" · "),href:y.href,environment:T?.slug,provider:m.provider,tags:h,score:Ge(t.query,m.name,N)})}if(!p)for(let m of e.listOperations({projectId:r.id,limit:500})){let T=m.environmentId?o.get(m.environmentId):void 0,h=ft(m.input,Or),_=m.kind.includes("deploy"),N=h[0]??m.kind,y=[m.kind,m.id,m.correlationId,m.state,...h].join(" ");u.push({type:_?"deployment":"operation",id:m.id,title:N,subtitle:`${m.kind} · ${m.state}`,href:`/server/activity?env=${encodeURIComponent(T?.slug??n[0]?.slug??"")}&operation=${encodeURIComponent(m.id)}`,environment:T?.slug,status:m.state,tags:[],score:Ge(t.query,N,y)})}for(let m of u)if(m.score===0)m.score=Ge(t.query,m.title,`${m.title} ${m.subtitle} ${m.environment??""} ${m.provider??""}`);let g={service:0,server:1,database:2,deployment:3,environment:4,project:5,operation:6};return u.filter((m)=>m.score>0).sort((m,T)=>T.score-m.score||g[m.type]-g[T.type]||m.title.localeCompare(T.title)||m.id.localeCompare(T.id)).slice(0,Math.min(50,Math.max(1,t.limit??20)))}import{createHash as Dr}from"node:crypto";var It=/^[a-z0-9](?:[a-z0-9_.-]{0,62})$/,wr=/^[A-Za-z_][A-Za-z0-9_]{0,127}$/,kr=/(?:secret|token|password|passwd|private.?key|api.?key|credential)/i,Pr=new Set(["image","build","command","entrypoint","environment","ports","volumes","networks","depends_on","healthcheck","restart","deploy","labels"]),yt=new Map([["privileged","Privileged containers are blocked."],["network_mode","Host/custom network modes are blocked."],["pid","Host PID namespaces are blocked."],["ipc","Host IPC namespaces are blocked."],["devices","Device access is blocked."],["cap_add","Additional Linux capabilities require an external policy exception."],["security_opt","Custom security options require an external policy exception."]]);function U(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function Ze(e){return Array.isArray(e)?e:e==null?[]:[e]}function xr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,63)||"compose-app"}function ae(e){if(Array.isArray(e))return e.map(String);if(typeof e==="string"&&e.trim())return["sh","-c",e];return}function We(e,t){let r=String(e??""),n=/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(r);if(!n)return t;let o=Number(n[1]);return Math.max(0,Math.round(o*(n[2]==="ms"?0.001:n[2]==="m"?60:n[2]==="h"?3600:1)))}function Lt(e){let t=/^(\d+(?:\.\d+)?)\s*(b|k|kb|kib|m|mb|mib|g|gb|gib)?$/i.exec(String(e??""));if(!t)return;let r=Number(t[1]),n=String(t[2]??"b").toLowerCase(),o=r*(n.startsWith("g")?1073741824:n.startsWith("m")?1048576:n.startsWith("k")?1024:1);return Math.max(1,Math.round(o/1024/1024))}function jr(e){if(e==null)return"";return/^\$\{([A-Za-z_][A-Za-z0-9_]*)(?::[-?][^}]*)?\}$/.exec(String(e))?.[1]}function St(e,t,r){let n={},o=Array.isArray(e)?e.map((a)=>{let[d,...u]=String(a).split("=");return[d,u.length?u.join("="):null]}):Object.entries(U(e));for(let[a,d]of o){let u=String(a);if(!wr.test(u)){r.push({severity:"error",path:`${t}.${u}`,code:"environment.name",message:"Environment variable names must use portable shell identifiers."});continue}let p=jr(d);if(p!==void 0){n[u]={secretRef:p||u};continue}if(kr.test(u)){r.push({severity:"error",path:`${t}.${u}`,code:"secret.literal",message:"Literal secret-like environment values are not stored.",alternative:`Use \${${u}} and supply ${u} through the secret store.`}),n[u]={secretRef:u};continue}n[u]=String(d??"")}return n}function Fr(e,t,r){let n=[];for(let[o,a]of Ze(e).entries()){let d,u,p="tcp";if(typeof a==="number")d=a;else if(typeof a==="string"){let[E,g]=a.split("/");p=g==="udp"?"udp":"tcp";let m=E.split(":");d=Number(m.at(-1)),u=m.length>1?Number(m.at(-2)):void 0}else{let E=U(a);d=Number(E.target),u=E.published==null?void 0:Number(E.published),p=E.protocol==="udp"?"udp":"tcp"}if(!Number.isInteger(d)||d<1||d>65535||u!=null&&(!Number.isInteger(u)||u<1||u>65535))r.push({severity:"error",path:`${t}[${o}]`,code:"port.invalid",message:"Ports must be integers from 1 through 65535."});else n.push({target:d,...u?{published:u}:{},protocol:p})}return n}function Mr(e,t,r,n){let o=[];for(let[a,d]of Ze(e).entries()){let u="",p="",E=!1,g="volume";if(typeof d==="string"){let m=d.split(":");u=m[0]??"",p=m[1]??"",E=m.slice(2).includes("ro"),g=u.startsWith("/")||u.startsWith(".")?"bind":"volume"}else{let m=U(d);u=String(m.source??""),p=String(m.target??""),E=m.read_only===!0,g=String(m.type??"volume")}if(g!=="volume"||u.startsWith("/")||u.startsWith(".")){n.push({severity:"error",path:`${r}[${a}]`,code:"volume.host_mount",message:"Host and bind mounts are blocked; use a named volume.",alternative:"Declare the volume at the top level and mount it by name."});continue}if(!It.test(u)||!p.startsWith("/")){n.push({severity:"error",path:`${r}[${a}]`,code:"volume.invalid",message:"A named source and absolute container target are required."});continue}if(!t.has(u))n.push({severity:"warning",path:`${r}[${a}]`,code:"volume.implicit",message:`Named volume ${u} is implicit and will be declared on export.`});t.add(u),o.push({source:u,target:p,readOnly:E})}return o}function zr(e){return Array.isArray(e)?e.map((t)=>({service:String(t),condition:"service_started"})):Object.entries(U(e)).map(([t,r])=>({service:t,condition:["service_started","service_healthy","service_completed_successfully"].includes(String(U(r).condition))?String(U(r).condition):"service_started"}))}function vt(e){let t=U(e);if(!Object.keys(t).length||t.disable===!0)return;let r=ae(t.test);return r?{test:r,intervalSeconds:We(t.interval,30),timeoutSeconds:We(t.timeout,5),retries:Math.max(1,Number(t.retries)||3),...t.start_period?{startPeriodSeconds:We(t.start_period,0)}:{}}:void 0}function qr(e,t,r){if(!e)return;let n=typeof e==="string"?{context:e}:U(e),o=String(n.context??"."),a=String(n.dockerfile??"Dockerfile");if(o.startsWith("/")||o.split("/").includes("..")||a.startsWith("/")||a.split("/").includes(".."))r.push({severity:"error",path:t,code:"build.traversal",message:"Build context and Dockerfile must stay inside the repository."});return{context:o,dockerfile:a,...n.target?{target:String(n.target)}:{},args:St(n.args,`${t}.args`,r)}}function Hr(e,t,r){let n=Array.isArray(e)?Object.fromEntries(e.map((a)=>String(a).split("=",2))):U(e),o=String(n["ts-cloud.domains"]??n["ts-cloud.domain"]??"").split(",").map((a)=>a.trim()).filter(Boolean);for(let a of o)if(!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i.test(a))r.push({severity:"error",path:t,code:"domain.invalid",message:`Invalid service domain ${a}.`});return o.filter((a)=>/\./.test(a))}function Br(e,t){let r=[],n=new Set,o=new Set,a=(d)=>{if(o.has(d))return;if(n.has(d)){t.push({severity:"error",path:`services.${d}.depends_on`,code:"dependency.cycle",message:"Service dependencies contain a cycle."});return}n.add(d);for(let u of e[d]?.dependsOn??[])if(!e[u.service])t.push({severity:"error",path:`services.${d}.depends_on.${u.service}`,code:"dependency.missing",message:`Dependency ${u.service} does not exist.`});else a(u.service);n.delete(d),o.add(d),r.push(d)};return Object.keys(e).sort().forEach(a),r}function Wr(e,t){if(Buffer.byteLength(e)>524288)throw Error("Compose source exceeds the 512 KiB limit");let r;try{r=U(Bun.YAML.parse(e))}catch(T){throw Error(`Compose YAML could not be parsed: ${T instanceof Error?T.message:String(T)}`)}let n=[],o=U(r.services),a=Object.keys(o);if(!a.length)n.push({severity:"error",path:"services",code:"services.required",message:"At least one service is required."});if(a.length>64)n.push({severity:"error",path:"services",code:"services.limit",message:"A Compose application may contain at most 64 services."});let d=new Set(Object.keys(U(r.volumes))),u=new Set(Object.keys(U(r.networks))),p={};for(let T of a.sort()){let h=`services.${T}`,_=U(o[T]);if(!It.test(T)){n.push({severity:"error",path:h,code:"service.name",message:"Service names must be portable lowercase identifiers."});continue}for(let[A,Nr]of yt)if(_[A]!=null&&_[A]!==!1&&(!Array.isArray(_[A])||_[A].length))n.push({severity:"error",path:`${h}.${A}`,code:`unsafe.${A}`,message:Nr});for(let A of Object.keys(_))if(!Pr.has(A)&&!yt.has(A))n.push({severity:"warning",path:`${h}.${A}`,code:"field.unsupported",message:`Compose field ${A} is not in the supported subset and will not be deployed.`});let N=_.image?String(_.image):void 0,y=qr(_.build,`${h}.build`,n);if(!N&&!y)n.push({severity:"error",path:h,code:"service.source",message:"Each service requires image or build."});if(N&&!N.includes("@sha256:")&&(!N.includes(":")||N.endsWith(":latest")))n.push({severity:"warning",path:`${h}.image`,code:"image.floating",message:`Image ${N} is not pinned to a digest or explicit tag.`});let L=Ze(_.networks).map((A)=>typeof A==="string"?A:String(U(A).name??"")).filter(Boolean);L.forEach((A)=>u.add(A));let v=U(_.deploy),I=U(v.resources),C=U(I.limits),w=["no","always","on-failure","unless-stopped"].includes(String(_.restart))?String(_.restart):"unless-stopped";p[T]={name:T,...N?{image:N}:{},...y?{build:y}:{},...ae(_.command)?{command:ae(_.command)}:{},...ae(_.entrypoint)?{entrypoint:ae(_.entrypoint)}:{},environment:St(_.environment,`${h}.environment`,n),ports:Fr(_.ports,`${h}.ports`,n),volumes:Mr(_.volumes,d,`${h}.volumes`,n),networks:L,dependsOn:zr(_.depends_on),...vt(_.healthcheck)?{healthCheck:vt(_.healthcheck)}:{},restart:w,...Number(C.cpus)>0?{cpu:Number(C.cpus)}:{},...Lt(C.memory)?{memoryMb:Lt(C.memory)}:{},replicas:Math.max(1,Math.min(100,Number(v.replicas)||1)),domains:Hr(_.labels,`${h}.labels`,n)}}let E=Br(p,n),g={apiVersion:"ts-cloud.dev/v1",kind:"ComposeApplication",metadata:{name:t.name.trim(),slug:xr(t.slug??t.name),projectId:t.projectId,environmentId:t.environmentId},spec:{services:p,networks:[...u].sort(),volumes:[...d].sort(),dependencyOrder:E}},m=Cd(g);return{valid:!n.some((T)=>T.severity==="error"),manifest:g,diagnostics:n,redactedSource:m,sourceHash:Dr("sha256").update(e).digest("hex")}}function Cd(e){let t=Object.fromEntries(Object.entries(e.spec.services).map(([r,n])=>[r,{...n.image?{image:n.image}:{},...n.build?{build:{context:n.build.context,dockerfile:n.build.dockerfile,...n.build.target?{target:n.build.target}:{},...Object.keys(n.build.args).length?{args:Object.fromEntries(Object.entries(n.build.args).map(([o,a])=>[o,typeof a==="string"?a:`\${${a.secretRef}:?required secret ${a.secretRef}}`]))}:{}}}:{},...n.command?{command:n.command}:{},...n.entrypoint?{entrypoint:n.entrypoint}:{},...Object.keys(n.environment).length?{environment:Object.fromEntries(Object.entries(n.environment).map(([o,a])=>[o,typeof a==="string"?a:`\${${a.secretRef}:?required secret ${a.secretRef}}`]))}:{},...n.ports.length?{ports:n.ports.map((o)=>`${o.published?`${o.published}:`:""}${o.target}${o.protocol==="udp"?"/udp":""}`)}:{},...n.volumes.length?{volumes:n.volumes.map((o)=>`${o.source}:${o.target}${o.readOnly?":ro":""}`)}:{},...n.networks.length?{networks:n.networks}:{},...n.dependsOn.length?{depends_on:Object.fromEntries(n.dependsOn.map((o)=>[o.service,{condition:o.condition}]))}:{},...n.healthCheck?{healthcheck:{test:n.healthCheck.test,interval:`${n.healthCheck.intervalSeconds}s`,timeout:`${n.healthCheck.timeoutSeconds}s`,retries:n.healthCheck.retries,...n.healthCheck.startPeriodSeconds!=null?{start_period:`${n.healthCheck.startPeriodSeconds}s`}:{}}}:{},restart:n.restart,...n.cpu||n.memoryMb||n.replicas!==1?{deploy:{replicas:n.replicas,resources:{limits:{...n.cpu?{cpus:String(n.cpu)}:{},...n.memoryMb?{memory:`${n.memoryMb}M`}:{}}}}}:{},...n.domains.length?{labels:{"ts-cloud.domains":n.domains.join(",")}}:{}}]));return Bun.YAML.stringify({services:t,...e.spec.networks.length?{networks:Object.fromEntries(e.spec.networks.map((r)=>[r,{}]))}:{},...e.spec.volumes.length?{volumes:Object.fromEntries(e.spec.volumes.map((r)=>[r,{}]))}:{}})}function Ed(e,t){let r=[],n=(o,a,d)=>{if(JSON.stringify(a)===JSON.stringify(d))return;if(a&&d&&typeof a==="object"&&typeof d==="object"&&!Array.isArray(a)&&!Array.isArray(d)){for(let u of[...new Set([...Object.keys(a),...Object.keys(d)])].sort())n(o?`${o}.${u}`:u,a[u],d[u]);return}r.push({path:o,...a!==void 0?{before:a}:{},...d!==void 0?{after:d}:{}})};return n("",e,t),r}import{createHash as bt}from"node:crypto";var Vr="2026-07-21T00:00:00.000Z",Ct=[{id:"bun-postgres-redis",name:"Bun + Postgres + Redis",description:"Web and worker services with durable Postgres and Redis dependencies.",category:"application",version:"1.0.0",sourceVersion:"oven/bun:1.2.21,postgres:17.5,redis:8.0.3",architecture:"web → Postgres + Redis; worker → Postgres + Redis",minimumResources:{cpu:2,memoryMb:3072},exposedServices:["web"],maintenanceNotes:"Back up the Postgres volume before major upgrades.",inputs:[{name:"domain",label:"Web domain",required:!0,secret:!1}],source:`services:
1508
1508
  web:
1509
1509
  image: oven/bun:1.2.21
1510
1510
  command: [bun, run, start]
@@ -1560,9 +1560,9 @@ volumes:
1560
1560
  volumes:
1561
1561
  wordpress-data: {}
1562
1562
  database-data: {}
1563
- `}];function Jr(){return Ct.map(({source:e,...t})=>({...t,source:`builtin:${t.id}`,lastVerifiedAt:Vr,builtin:!0,checksum:bt("sha256").update(e).digest("hex"),exposedServices:[...t.exposedServices],inputs:t.inputs.map((r)=>({...r}))}))}function PA(e,t){return Jr().find((r)=>r.id===e&&(!t||r.version===t))}function vd(e,t,r,n){let o=Ct.find((d)=>d.id===e&&(!n||d.version===n));if(!o)throw Error(`Compose template ${e}${n?`@${n}`:""} was not found`);let a=o.source;for(let d of o.inputs){let u=t[d.name]??("default"in d?d.default:void 0);if(d.required&&!u)throw Error(`Template input ${d.name} is required`);if(u&&!/^[A-Za-z0-9._:/@+-]{1,255}$/.test(u))throw Error(`Template input ${d.name} contains unsupported characters`);a=a.replaceAll(`{{${d.name}}}`,u??"")}return Wr(a,r)}function xI(e,t){if(Buffer.byteLength(e)>1048576)throw Error("Compose catalog exceeds the 1 MiB limit");let r;try{r=JSON.parse(e)}catch{throw Error("Compose catalog must be valid JSON")}if(r.apiVersion!=="ts-cloud.dev/compose-catalog/v1"||!Array.isArray(r.templates))throw Error("Compose catalog must use ts-cloud.dev/compose-catalog/v1 and contain templates");let n=String(r.source??"").trim();if(!/^https:\/\//.test(n)&&!n.startsWith("file:"))throw Error("Compose catalog source must be HTTPS or an explicit file: source");let o=[],a=[];for(let[d,u]of r.templates.slice(0,100).entries()){let p=u&&typeof u==="object"&&!Array.isArray(u)?u:{},E=`templates[${d}]`,g=String(p.compose??""),m=bt("sha256").update(g).digest("hex");if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(String(p.id??""))||!/^\d+\.\d+\.\d+$/.test(String(p.version??""))){o.push({severity:"error",path:E,code:"template.identity",message:"Template id and semantic version are required."});continue}if(String(p.checksum??"")!==m){o.push({severity:"error",path:`${E}.checksum`,code:"template.checksum",message:"Template checksum does not match its Compose source."});continue}let T=Wr(g,{name:String(p.name??p.id),projectId:t.projectId,environmentId:t.environmentId});o.push(...T.diagnostics.map((_)=>({..._,path:`${E}.compose.${_.path}`})));let h={id:String(p.id),name:String(p.name??p.id),description:String(p.description??""),category:String(p.category??"custom"),version:String(p.version),source:n,sourceVersion:String(p.sourceVersion??p.version),architecture:String(p.architecture??Object.keys(T.manifest.spec.services).join(" + ")),minimumResources:{cpu:Math.max(0.1,Number(p.minimumResources?.cpu)||1),memoryMb:Math.max(128,Number(p.minimumResources?.memoryMb)||512)},exposedServices:Array.isArray(p.exposedServices)?p.exposedServices.map(String):[],maintenanceNotes:String(p.maintenanceNotes??""),lastVerifiedAt:String(p.lastVerifiedAt??""),inputs:[],checksum:m,builtin:!1};a.push({template:h,parsed:T})}return{valid:!o.some((d)=>d.severity==="error"),source:n,templates:a,diagnostics:o}}function OI(e,t,r,n,o,a){let d=PA(r,a);if(!d)throw Error(`Compose template ${r}@${a} was not found`);let u=vd(r,n,o,a);return{template:d,parsed:u,templateChanges:Ed(t,u.manifest),userChanges:Ed(t,e)}}var Ce=/^[a-z0-9][a-z0-9_.-]{0,62}$/;function D(e){return`'${e.replaceAll("'","'\\''")}'`}function Io(e){return`${e.metadata.slug}-${e.metadata.environmentId.slice(0,8)}`.replace(/[^a-z0-9_-]/g,"-").slice(0,63)}function _I(e,t,r={}){let n=Io(e),o=`/opt/ts-cloud/compose/${n}`,a=`${o}/compose.yaml`,d=`docker compose --project-name ${D(n)} --file ${D(a)}`;if(r.service&&!Ce.test(r.service))throw Error("Unsafe Compose service name");if(t==="deploy"||t==="redeploy"){let u=Buffer.from(Cd(e)).toString("base64");return`install -d -m 0750 ${D(o)} && printf %s ${D(u)} | base64 --decode > ${D(a)} && chmod 0640 ${D(a)} && ${d} config --quiet && ${d} up --detach --remove-orphans --wait${t==="redeploy"?" --force-recreate":""}`}if(t==="start")return`${d} start${r.service?` ${D(r.service)}`:""}`;if(t==="stop")return`${d} stop${r.service?` ${D(r.service)}`:""}`;if(t==="status")return`${d} ps --format json`;return`${d} down --remove-orphans${r.removeVolumes?" --volumes":""}`}function LI(e,t,r){if(!Ce.test(t)||!Number.isInteger(r)||r<0||r>100)throw Error("Scale requires a safe service name and 0-100 replicas");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} up --detach --wait --scale ${D(`${t}=${r}`)}`}function Td(e,t,r=200){if(!Ce.test(t))throw Error("Unsafe Compose service name");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} logs --no-color --timestamps --tail ${Math.max(1,Math.min(2000,Math.floor(r)))} ${D(t)}`}function wd(e,t,r=["sh"]){if(!Ce.test(t)||!r.length||r.some((o)=>o.includes("\x00")||o.length>1024))throw Error("Unsafe Compose shell request");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} exec ${D(t)} ${r.map(D).join(" ")}`}import{mkdir as it,readdir as hn,rm as Nn,stat as fn}from"node:fs/promises";import{basename as yn,resolve as jt,sep as Ln}from"node:path";class $i extends Error{constructor(){super("Operation cancellation was requested")}}class bo extends Error{timeoutSeconds;constructor(e){super(`Operation exceeded its ${e}s timeout`);this.timeoutSeconds=e}}class ae extends Error{errorClass;constructor(e,t){super(e);this.errorClass=t}}var Ae={project:2,environment:1,provider:2,builds:1},Kr=30,At=16384,$r=["succeeded","failed","cancelled","timed_out"],et=new Map,Ot=new WeakMap;function Ut(e){if(e.path===":memory:"){let n=Ot.get(e);if(n)return n;let o=new Set;return Ot.set(e,o),o}let t=et.get(e.path);if(t)return t;let r=new Set;return et.set(e.path,r),r}function Y(e){return typeof e==="string"&&e?e:void 0}function Qr(e){try{let t=JSON.parse(String(e));return Array.isArray(t)?t.map(String):[]}catch{return[]}}function Gr(e){return{operationId:String(e.operation_id),lockKey:Y(e.lock_key),providerKey:Y(e.provider_key),buildSlot:Number(e.build_slot)===1,maxAttempts:Number(e.max_attempts),availableAt:String(e.available_at),timeoutSeconds:Number(e.timeout_seconds),heartbeatAt:Y(e.heartbeat_at),currentStep:Y(e.current_step),blockedReason:Y(e.blocked_reason),retryClasses:Qr(e.retry_classes),resumePolicy:String(e.resume_policy),cancellationMode:String(e.cancellation_mode),retentionUntil:String(e.retention_until),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function kt(e){return{sequence:Number(e.sequence),id:String(e.id),operationId:String(e.operation_id),stream:String(e.stream),step:Y(e.step),message:String(e.message),redacted:Number(e.redacted)===1,truncated:Number(e.truncated)===1,createdAt:String(e.created_at)}}function M(e,t,r){return Number.isFinite(e)?Math.min(r,Math.max(1,Math.floor(e))):t}class c{controlPlane;nowFn;idFn;workerId;leaseMs;limits;constructor(e,t={}){this.controlPlane=e;this.workerId=t.workerId??`worker:${process.pid}:${crypto.randomUUID()}`,this.leaseMs=M(t.leaseMs,60000,3600000),this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID());let r=e.getSetting("queue.concurrency");this.limits={project:M(t.limits?.project??r?.project,Ae.project,100),environment:M(t.limits?.environment??r?.environment,Ae.environment,100),provider:M(t.limits?.provider??r?.provider,Ae.provider,100),builds:M(t.limits?.builds??r?.builds,Ae.builds,100)}}now(){return this.nowFn().toISOString()}leaseExpiry(){return new Date(this.nowFn().getTime()+this.leaseMs).toISOString()}enqueue(e){let t=this.controlPlane.createOperation(e);if(this.getJob(t.id))return this.view(t.id);let n=this.now(),o=M(e.maxAttempts,1,20),a=M(e.timeoutSeconds,1800,86400),d=M(e.retentionDays,Kr,3650),u=e.availableAt?new Date(e.availableAt).toISOString():n,p=new Date(this.nowFn().getTime()+d*24*60*60*1000).toISOString();this.controlPlane.database.run(`INSERT OR IGNORE INTO operation_jobs (operation_id, lock_key, provider_key, build_slot, max_attempts, available_at, timeout_seconds, retry_classes, resume_policy, cancellation_mode, retention_until, created_at, updated_at)
1563
+ `}];function Jr(){return Ct.map(({source:e,...t})=>({...t,source:`builtin:${t.id}`,lastVerifiedAt:Vr,builtin:!0,checksum:bt("sha256").update(e).digest("hex"),exposedServices:[...t.exposedServices],inputs:t.inputs.map((r)=>({...r}))}))}function PA(e,t){return Jr().find((r)=>r.id===e&&(!t||r.version===t))}function vd(e,t,r,n){let o=Ct.find((d)=>d.id===e&&(!n||d.version===n));if(!o)throw Error(`Compose template ${e}${n?`@${n}`:""} was not found`);let a=o.source;for(let d of o.inputs){let u=t[d.name]??("default"in d?d.default:void 0);if(d.required&&!u)throw Error(`Template input ${d.name} is required`);if(u&&!/^[A-Za-z0-9._:/@+-]{1,255}$/.test(u))throw Error(`Template input ${d.name} contains unsupported characters`);a=a.replaceAll(`{{${d.name}}}`,u??"")}return Wr(a,r)}function xI(e,t){if(Buffer.byteLength(e)>1048576)throw Error("Compose catalog exceeds the 1 MiB limit");let r;try{r=JSON.parse(e)}catch{throw Error("Compose catalog must be valid JSON")}if(r.apiVersion!=="ts-cloud.dev/compose-catalog/v1"||!Array.isArray(r.templates))throw Error("Compose catalog must use ts-cloud.dev/compose-catalog/v1 and contain templates");let n=String(r.source??"").trim();if(!/^https:\/\//.test(n)&&!n.startsWith("file:"))throw Error("Compose catalog source must be HTTPS or an explicit file: source");let o=[],a=[];for(let[d,u]of r.templates.slice(0,100).entries()){let p=u&&typeof u==="object"&&!Array.isArray(u)?u:{},E=`templates[${d}]`,g=String(p.compose??""),m=bt("sha256").update(g).digest("hex");if(!/^[a-z0-9][a-z0-9-]{1,62}$/.test(String(p.id??""))||!/^\d+\.\d+\.\d+$/.test(String(p.version??""))){o.push({severity:"error",path:E,code:"template.identity",message:"Template id and semantic version are required."});continue}if(String(p.checksum??"")!==m){o.push({severity:"error",path:`${E}.checksum`,code:"template.checksum",message:"Template checksum does not match its Compose source."});continue}let T=Wr(g,{name:String(p.name??p.id),projectId:t.projectId,environmentId:t.environmentId});o.push(...T.diagnostics.map((_)=>({..._,path:`${E}.compose.${_.path}`})));let h={id:String(p.id),name:String(p.name??p.id),description:String(p.description??""),category:String(p.category??"custom"),version:String(p.version),source:n,sourceVersion:String(p.sourceVersion??p.version),architecture:String(p.architecture??Object.keys(T.manifest.spec.services).join(" + ")),minimumResources:{cpu:Math.max(0.1,Number(p.minimumResources?.cpu)||1),memoryMb:Math.max(128,Number(p.minimumResources?.memoryMb)||512)},exposedServices:Array.isArray(p.exposedServices)?p.exposedServices.map(String):[],maintenanceNotes:String(p.maintenanceNotes??""),lastVerifiedAt:String(p.lastVerifiedAt??""),inputs:[],checksum:m,builtin:!1};a.push({template:h,parsed:T})}return{valid:!o.some((d)=>d.severity==="error"),source:n,templates:a,diagnostics:o}}function OI(e,t,r,n,o,a){let d=PA(r,a);if(!d)throw Error(`Compose template ${r}@${a} was not found`);let u=vd(r,n,o,a);return{template:d,parsed:u,templateChanges:Ed(t,u.manifest),userChanges:Ed(t,e)}}var Re=/^[a-z0-9][a-z0-9_.-]{0,62}$/;function D(e){return`'${e.replaceAll("'","'\\''")}'`}function Io(e){return`${e.metadata.slug}-${e.metadata.environmentId.slice(0,8)}`.replace(/[^a-z0-9_-]/g,"-").slice(0,63)}function _I(e,t,r={}){let n=Io(e),o=`/opt/ts-cloud/compose/${n}`,a=`${o}/compose.yaml`,d=`docker compose --project-name ${D(n)} --file ${D(a)}`;if(r.service&&!Re.test(r.service))throw Error("Unsafe Compose service name");if(t==="deploy"||t==="redeploy"){let u=Buffer.from(Cd(e)).toString("base64");return`install -d -m 0750 ${D(o)} && printf %s ${D(u)} | base64 --decode > ${D(a)} && chmod 0640 ${D(a)} && ${d} config --quiet && ${d} up --detach --remove-orphans --wait${t==="redeploy"?" --force-recreate":""}`}if(t==="start")return`${d} start${r.service?` ${D(r.service)}`:""}`;if(t==="stop")return`${d} stop${r.service?` ${D(r.service)}`:""}`;if(t==="status")return`${d} ps --format json`;return`${d} down --remove-orphans${r.removeVolumes?" --volumes":""}`}function LI(e,t,r){if(!Re.test(t)||!Number.isInteger(r)||r<0||r>100)throw Error("Scale requires a safe service name and 0-100 replicas");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} up --detach --wait --scale ${D(`${t}=${r}`)}`}function Td(e,t,r=200){if(!Re.test(t))throw Error("Unsafe Compose service name");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} logs --no-color --timestamps --tail ${Math.max(1,Math.min(2000,Math.floor(r)))} ${D(t)}`}function wd(e,t,r=["sh"]){if(!Re.test(t)||!r.length||r.some((o)=>o.includes("\x00")||o.length>1024))throw Error("Unsafe Compose shell request");let n=Io(e);return`docker compose --project-name ${D(n)} --file ${D(`/opt/ts-cloud/compose/${n}/compose.yaml`)} exec ${D(t)} ${r.map(D).join(" ")}`}import{mkdir as it,readdir as hn,rm as Nn,stat as fn}from"node:fs/promises";import{basename as yn,resolve as jt,sep as Ln}from"node:path";class $i extends Error{constructor(){super("Operation cancellation was requested")}}class bo extends Error{timeoutSeconds;constructor(e){super(`Operation exceeded its ${e}s timeout`);this.timeoutSeconds=e}}class ce extends Error{errorClass;constructor(e,t){super(e);this.errorClass=t}}var Ae={project:2,environment:1,provider:2,builds:1},Kr=30,At=16384,$r=["succeeded","failed","cancelled","timed_out"],et=new Map,Ot=new WeakMap;function Ut(e){if(e.path===":memory:"){let n=Ot.get(e);if(n)return n;let o=new Set;return Ot.set(e,o),o}let t=et.get(e.path);if(t)return t;let r=new Set;return et.set(e.path,r),r}function Y(e){return typeof e==="string"&&e?e:void 0}function Qr(e){try{let t=JSON.parse(String(e));return Array.isArray(t)?t.map(String):[]}catch{return[]}}function Gr(e){return{operationId:String(e.operation_id),lockKey:Y(e.lock_key),providerKey:Y(e.provider_key),buildSlot:Number(e.build_slot)===1,maxAttempts:Number(e.max_attempts),availableAt:String(e.available_at),timeoutSeconds:Number(e.timeout_seconds),heartbeatAt:Y(e.heartbeat_at),currentStep:Y(e.current_step),blockedReason:Y(e.blocked_reason),retryClasses:Qr(e.retry_classes),resumePolicy:String(e.resume_policy),cancellationMode:String(e.cancellation_mode),retentionUntil:String(e.retention_until),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function kt(e){return{sequence:Number(e.sequence),id:String(e.id),operationId:String(e.operation_id),stream:String(e.stream),step:Y(e.step),message:String(e.message),redacted:Number(e.redacted)===1,truncated:Number(e.truncated)===1,createdAt:String(e.created_at)}}function M(e,t,r){return Number.isFinite(e)?Math.min(r,Math.max(1,Math.floor(e))):t}class c{controlPlane;nowFn;idFn;workerId;leaseMs;limits;constructor(e,t={}){this.controlPlane=e;this.workerId=t.workerId??`worker:${process.pid}:${crypto.randomUUID()}`,this.leaseMs=M(t.leaseMs,60000,3600000),this.nowFn=t.now??(()=>new Date),this.idFn=t.id??(()=>crypto.randomUUID());let r=e.getSetting("queue.concurrency");this.limits={project:M(t.limits?.project??r?.project,Ae.project,100),environment:M(t.limits?.environment??r?.environment,Ae.environment,100),provider:M(t.limits?.provider??r?.provider,Ae.provider,100),builds:M(t.limits?.builds??r?.builds,Ae.builds,100)}}now(){return this.nowFn().toISOString()}leaseExpiry(){return new Date(this.nowFn().getTime()+this.leaseMs).toISOString()}enqueue(e){let t=this.controlPlane.createOperation(e);if(this.getJob(t.id))return this.view(t.id);let n=this.now(),o=M(e.maxAttempts,1,20),a=M(e.timeoutSeconds,1800,86400),d=M(e.retentionDays,Kr,3650),u=e.availableAt?new Date(e.availableAt).toISOString():n,p=new Date(this.nowFn().getTime()+d*24*60*60*1000).toISOString();this.controlPlane.database.run(`INSERT OR IGNORE INTO operation_jobs (operation_id, lock_key, provider_key, build_slot, max_attempts, available_at, timeout_seconds, retry_classes, resume_policy, cancellation_mode, retention_until, created_at, updated_at)
1564
1564
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[t.id,e.lockKey??e.resourceId??null,e.providerKey??null,e.buildSlot?1:0,o,u,a,JSON.stringify([...new Set(e.retryClasses??[])]),e.resumePolicy??"fail",e.cancellationMode??"cooperative",p,n,n]),this.appendLog(t.id,"Queued for durable execution.",{stream:"system"});let E=this.view(t.id);return this.notifyAvailable(),E}onAvailable(e){let t=Ut(this.controlPlane);return t.add(e),()=>{if(t.delete(e),t.size===0&&this.controlPlane.path!==":memory:")et.delete(this.controlPlane.path)}}notifyAvailable(){for(let e of Ut(this.controlPlane))e()}getJob(e){let t=this.controlPlane.database.query("SELECT * FROM operation_jobs WHERE operation_id=?").get(e);return t?Gr(t):void 0}view(e){let t=this.controlPlane.getOperation(e),r=this.getJob(e);if(!t||!r)return;let n;if(t.state==="queued")n={ahead:Number(this.controlPlane.database.query("SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='queued' AND j.available_at<=? AND (o.priority>? OR (o.priority=? AND o.created_at<?))").get(this.now(),t.priority,t.priority,t.createdAt)?.count??0),precision:"bounded"};return{operation:t,job:r,approximatePosition:n}}list(e={}){return this.controlPlane.listOperations({projectId:e.projectId,state:e.state,limit:e.limit??200}).map((t)=>this.view(t.id)).filter((t)=>!!t)}configureConcurrency(e,t={}){let r={project:M(e.project,this.limits.project,100),environment:M(e.environment,this.limits.environment,100),provider:M(e.provider,this.limits.provider,100),builds:M(e.builds,this.limits.builds,100)};return Object.assign(this.limits,r),this.controlPlane.setSetting("queue.concurrency",r),this.controlPlane.appendEvent({organizationId:t.organizationId,actorId:t.actorId,type:"queue.concurrency.updated",level:"warning",payload:r}),r}runningCount(e,t){return Number(this.controlPlane.database.query(e).get(...t)?.count??0)}blockReason(e,t){if(t.lockKey){if(this.controlPlane.database.query("SELECT * FROM operation_locks WHERE lock_key=? AND operation_id!=? AND lease_expires_at>?").get(t.lockKey,e.id,this.now()))return`resource_lock:${t.lockKey}`}if(e.projectId&&this.runningCount("SELECT COUNT(*) AS count FROM operations WHERE state='running' AND project_id=?",[e.projectId])>=this.limits.project)return"project_concurrency";if(e.environmentId&&this.runningCount("SELECT COUNT(*) AS count FROM operations WHERE state='running' AND environment_id=?",[e.environmentId])>=this.limits.environment)return"environment_concurrency";if(t.providerKey&&this.runningCount("SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND j.provider_key=?",[t.providerKey])>=this.limits.provider)return"provider_concurrency";if(t.buildSlot&&this.runningCount("SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND j.build_slot=1",[])>=this.limits.builds)return"build_concurrency";return}claim(e){return this.controlPlane.transaction(()=>{let t=this.now();this.controlPlane.database.run("DELETE FROM operation_locks WHERE lease_expires_at<=?",[t]);let r=this.controlPlane.getOperation(e),n=r?this.getJob(r.id):void 0;if(!r||!n||r.state!=="queued"||n.availableAt>t)return;if(r.cancelRequestedAt){this.controlPlane.transitionOperation(r.id,{to:"cancelled",expectedVersion:r.version,output:{cancelledBeforeStart:!0}}),this.appendLog(r.id,"Cancelled before execution began.",{stream:"system"});return}let o=this.blockReason(r,n);if(o){this.controlPlane.database.run("UPDATE operation_jobs SET blocked_reason=?, updated_at=? WHERE operation_id=?",[o,t,r.id]);return}let a=this.controlPlane.claimOperation(r.id,this.workerId,this.leaseMs);if(!a)return;let d=a.leaseExpiresAt??this.leaseExpiry();if(n.lockKey)this.controlPlane.database.run("INSERT INTO operation_locks (lock_key, operation_id, lease_owner, lease_expires_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",[n.lockKey,r.id,this.workerId,d,t,t]);return this.controlPlane.database.run("UPDATE operation_jobs SET heartbeat_at=?, blocked_reason=NULL, updated_at=? WHERE operation_id=?",[t,t,r.id]),this.appendLog(r.id,`Claimed by ${this.workerId}; attempt ${a.attempt}.`,{stream:"system"}),this.view(r.id)})}claimNext(e){let t=this.now(),r=e?.length?`AND o.kind IN (${e.map(()=>"?").join(",")})`:"",n=this.controlPlane.database.query(`SELECT o.id FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='queued' AND j.available_at<=? ${r} ORDER BY o.priority DESC, o.created_at ASC, o.rowid ASC LIMIT 100`).all(t,...e??[]);for(let o of n){let a=this.claim(String(o.id));if(a)return a}return}heartbeat(e,t){let r=this.controlPlane.getOperation(e);if(!r||r.state!=="running"||r.leaseOwner!==this.workerId)throw Error("Operation lease is not owned by this worker");let n=this.now(),o=this.leaseExpiry(),a=this.getJob(e);if(this.controlPlane.database.run("UPDATE operations SET lease_expires_at=?, updated_at=?, version=version+1 WHERE id=? AND state='running' AND lease_owner=? AND version=?",[o,n,e,this.workerId,r.version]).changes!==1)throw Error("Operation lease changed before heartbeat");if(this.controlPlane.database.run("UPDATE operation_jobs SET heartbeat_at=?, current_step=COALESCE(?, current_step), updated_at=? WHERE operation_id=?",[n,t??null,n,e]),a?.lockKey)this.controlPlane.database.run("UPDATE operation_locks SET lease_expires_at=?, updated_at=? WHERE lock_key=? AND operation_id=? AND lease_owner=?",[o,n,a.lockKey,e,this.workerId]);if(t&&t!==a?.currentStep)this.controlPlane.appendEvent({projectId:r.projectId,operationId:e,resourceId:r.resourceId,actorId:r.actorId,correlationId:r.correlationId,type:"operation.step",payload:{step:t}})}appendLog(e,t,r={}){if(!this.getJob(e))throw Error(`Queue job ${e} was not found`);let n=t,o=!1;for(let g of r.secrets??[])if(g&&n.includes(g))n=n.split(g).join("[REDACTED]"),o=!0;let a=s({message:n});if(a.message!==n)o=!0;n=a.message??"[output unavailable]";let d=Buffer.from(n),u=d.byteLength>At;if(u)n=`${d.subarray(0,At-32).toString("utf8")}
1565
- [output truncated]`;let p=this.idFn(),E=this.now();return this.controlPlane.database.run("INSERT INTO operation_logs (id, operation_id, stream, step, message, redacted, truncated, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",[p,e,r.stream??"stdout",r.step??null,n,o?1:0,u?1:0,E]),kt(this.controlPlane.database.query("SELECT * FROM operation_logs WHERE id=?").get(p))}logs(e,t={}){let r=Math.min(1000,Math.max(1,t.limit??200));return this.controlPlane.database.query("SELECT * FROM operation_logs WHERE operation_id=? AND sequence>? ORDER BY sequence ASC LIMIT ?").all(e,t.after??0,r).map(kt)}requestCancellation(e,t){let r=this.controlPlane.getOperation(e);if(!r||$r.includes(r.state))throw Error("Only queued or running operations can be cancelled");let n=this.controlPlane.requestCancellation(e);if(this.controlPlane.appendEvent({projectId:r.projectId,operationId:e,resourceId:r.resourceId,actorId:t,correlationId:r.correlationId,type:"operation.cancellation_requested",level:"warning",payload:{state:r.state}}),this.appendLog(e,r.state==="queued"?"Cancellation accepted before execution.":"Cancellation requested; waiting for the current provider step.",{stream:"system"}),n.state==="queued")return this.finish(e,"cancelled",{cancelledBeforeStart:!0});return n}retry(e,t,r={}){let n=this.controlPlane.getOperation(e),o=this.getJob(e);if(!n||!o||!["failed","cancelled","timed_out"].includes(n.state))throw Error("Only failed, cancelled, or timed-out queue jobs can be retried");if(n.attempt>=o.maxAttempts)throw Error(`Operation reached its ${o.maxAttempts}-attempt limit`);if(!o.retryClasses.includes(t))throw Error(`Retry class ${t} is not allowed for this operation`);let a=this.controlPlane.transitionOperation(e,{to:"queued",expectedVersion:n.version,error:`Retry requested after ${t}`}),d=new Date(this.nowFn().getTime()+Math.max(0,r.delayMs??0)).toISOString();this.controlPlane.database.run("UPDATE operations SET cancel_requested_at=NULL, finished_at=NULL WHERE id=?",[e]),this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason=NULL, updated_at=? WHERE operation_id=?",[d,this.now(),e]),this.controlPlane.appendEvent({projectId:n.projectId,operationId:e,resourceId:n.resourceId,actorId:r.actorId,correlationId:n.correlationId,type:"operation.retry_requested",payload:{errorClass:t,availableAt:d,nextAttempt:n.attempt+1}}),this.appendLog(e,`Retry queued for error class ${t}.`,{stream:"system"});let u=this.controlPlane.getOperation(a.id);return this.notifyAvailable(),u}release(e){this.controlPlane.database.run("DELETE FROM operation_locks WHERE operation_id=?",[e])}finish(e,t,r={},n){let o=this.controlPlane.getOperation(e);if(!o)throw Error(`Operation ${e} was not found`);let a=this.controlPlane.transitionOperation(e,{to:t,expectedVersion:o.version,output:r,error:n});return this.release(e),a}complete(e,t={}){let r=this.controlPlane.getOperation(e);if(!r||r.state!=="running"||r.leaseOwner!==this.workerId)throw Error("Only the lease owner can complete a running operation");return this.appendLog(e,"Operation completed successfully.",{stream:"system"}),this.finish(e,"succeeded",t)}fail(e,t,r={}){let n=this.controlPlane.getOperation(e);if(!n||n.state!=="running"||n.leaseOwner!==this.workerId)throw Error("Only the lease owner can fail a running operation");return this.appendLog(e,t,{stream:"stderr"}),this.finish(e,"failed",r,t)}async runOne(e){let t=this.claimNext(Object.keys(e));if(!t)return{handled:!1};let{operation:r,job:n}=t,o=e[r.kind];if(!o)return{handled:!1};let a=new AbortController,d=!1,u=setTimeout(()=>{d=!0,a.abort(new bo(n.timeoutSeconds))},n.timeoutSeconds*1000),p=setInterval(()=>{try{this.heartbeat(r.id)}catch{}},Math.max(250,Math.floor(this.leaseMs/3))),E=setInterval(()=>{if(this.controlPlane.getOperation(r.id)?.cancelRequestedAt)a.abort(new $i)},100),g={operation:r,signal:a.signal,log:(m,T)=>this.appendLog(r.id,m,T),checkpoint:(m,T)=>{this.heartbeat(r.id,m),this.appendLog(r.id,T??m,{stream:"step",step:m})},heartbeat:()=>this.heartbeat(r.id),cancellationRequested:()=>!!this.controlPlane.getOperation(r.id)?.cancelRequestedAt,throwIfCancellationRequested:()=>{if(this.controlPlane.getOperation(r.id)?.cancelRequestedAt)throw new $i}};try{let m=await Promise.race([o(g),new Promise((_,N)=>a.signal.addEventListener("abort",()=>N(a.signal.reason),{once:!0}))]);if(this.controlPlane.getOperation(r.id).cancelRequestedAt){let _=n.cancellationMode==="provider_non_cancellable";return this.appendLog(r.id,_?"Provider step completed after cancellation was requested; reconciliation is required.":"Operation cancelled cooperatively.",{stream:"system"}),{handled:!0,operation:this.finish(r.id,"cancelled",{providerCompleted:_,reconciliationRequired:_}),terminalState:"cancelled"}}return{handled:!0,operation:this.complete(r.id,m??{}),terminalState:"succeeded"}}catch(m){if(d||m instanceof bo)return this.appendLog(r.id,`Timed out after ${n.timeoutSeconds}s.`,{stream:"system"}),{handled:!0,operation:this.finish(r.id,"timed_out",{reconciliationRequired:n.cancellationMode==="provider_non_cancellable"},m instanceof Error?m.message:String(m)),terminalState:"timed_out"};if(m instanceof $i||this.controlPlane.getOperation(r.id)?.cancelRequestedAt)return{handled:!0,operation:this.finish(r.id,"cancelled",{cooperativelyCancelled:!0}),terminalState:"cancelled"};if(m instanceof ae&&n.retryClasses.includes(m.errorClass)&&r.attempt<n.maxAttempts){let _=this.controlPlane.getOperation(r.id);this.controlPlane.transitionOperation(r.id,{to:"queued",expectedVersion:_.version,error:m.message});let N=Math.min(60000,1000*2**Math.max(0,r.attempt-1)),y=new Date(this.nowFn().getTime()+N).toISOString();return this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason=?, updated_at=? WHERE operation_id=?",[y,`retry_backoff:${m.errorClass}`,this.now(),r.id]),this.release(r.id),this.appendLog(r.id,`Retryable ${m.errorClass} failure; next attempt is delayed.`,{stream:"system"}),{handled:!0,operation:this.controlPlane.getOperation(r.id),requeued:!0}}let T=m instanceof Error?m.message:String(m);return this.appendLog(r.id,T,{stream:"stderr"}),{handled:!0,operation:this.finish(r.id,"failed",{},T),terminalState:"failed"}}finally{clearTimeout(u),clearInterval(p),clearInterval(E)}}recoverExpired(){let e=this.controlPlane.database.query("SELECT o.id FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND (o.lease_expires_at IS NULL OR o.lease_expires_at<=?)").all(this.now()),t={requeued:0,failed:0,cancelled:0};for(let r of e){let n=this.controlPlane.getOperation(String(r.id)),o=this.getJob(n.id);if(this.release(n.id),n.cancelRequestedAt){this.finish(n.id,"cancelled",{recoveredAfterWorkerLoss:!0}),t.cancelled++;continue}if(o.resumePolicy==="requeue"&&n.attempt<o.maxAttempts)this.controlPlane.transitionOperation(n.id,{to:"queued",expectedVersion:n.version,error:"Worker lease expired; safely requeued from the last checkpoint."}),this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason='worker_restart', updated_at=? WHERE operation_id=?",[this.now(),this.now(),n.id]),this.appendLog(n.id,"Worker lease expired; operation requeued from its persisted checkpoint.",{stream:"system"}),t.requeued++;else this.finish(n.id,"failed",{recoverable:!0,lastCheckpoint:o.currentStep??null},"Worker lease expired; retry explicitly after reconciling provider state."),t.failed++}return t}clearCompleted(e={}){let t=this.now(),r=[t],n=e.projectId?"AND o.project_id=?":"";if(e.projectId)r.push(e.projectId);let o=e.before?"AND o.finished_at<=?":"";if(e.before)r.push(new Date(e.before).toISOString());let a=this.controlPlane.database.query(`SELECT o.id, o.project_id, o.correlation_id FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state IN ('succeeded','failed','cancelled','timed_out') AND j.retention_until<=? ${n} ${o}`).all(...r);for(let d of a)this.controlPlane.appendEvent({projectId:Y(d.project_id),actorId:e.actorId,correlationId:String(d.correlation_id),type:"queue.history.cleared",level:"warning",payload:{operationId:String(d.id),retentionCutoff:t}}),this.controlPlane.database.run("DELETE FROM operations WHERE id=?",[String(d.id)]);return a.length}}function Xt(e,t,r){if(!Number.isFinite(e))return t;return Math.min(r,Math.max(1,Math.floor(e)))}class Co{queue;handlers;parallelism;pollIntervalMs;onResult;onError;waits=new Map;nextWaitId=0;lanes=[];running=!1;unsubscribeAvailability;constructor(e,t,r={}){this.queue=e;this.handlers=t;this.parallelism=Xt(r.parallelism,4,100),this.pollIntervalMs=Xt(r.pollIntervalMs,5000,60000),this.onResult=r.onResult,this.onError=r.onError}get active(){return this.running}start(){if(this.running)return this;return this.running=!0,this.unsubscribeAvailability=this.queue.onAvailable(()=>this.wake()),this.lanes=Array.from({length:this.parallelism},(e,t)=>this.runLane(t)),this}stop(){this.running=!1,this.unsubscribeAvailability?.(),this.unsubscribeAvailability=void 0,this.wake()}wake(){for(let{resolve:e,timer:t}of this.waits.values()){if(t)clearTimeout(t);e()}this.waits.clear()}async settled(){await Promise.allSettled(this.lanes)}async drain(){let e=[];while(!0){let t=await Promise.all(Array.from({length:this.parallelism},()=>this.queue.runOne(this.handlers)));if(e.push(...t.filter((r)=>r.handled)),!t.some((r)=>r.handled))return e}}wait(e){return new Promise((t)=>{let r=++this.nextWaitId,n=e?setTimeout(()=>{this.waits.delete(r),t()},this.pollIntervalMs):void 0;n?.unref?.(),this.waits.set(r,{resolve:t,timer:n})})}async runLane(e){while(this.running){try{let t=await this.queue.runOne(this.handlers);if(!this.running)break;if(t.handled){this.onResult?.(t),this.wake();continue}}catch(t){this.onError?.(t)}await this.wait(e===0)}}}import{createHash as an}from"node:crypto";var dn=/^[a-f0-9]{40,64}$/i,ln=/^[A-Z][A-Z0-9_]{1,127}$/;function q(e){return typeof e==="string"&&e?e:void 0}function J(e){try{return JSON.parse(String(e))}catch{return{}}}function un(e){let t=J(e);return Array.isArray(t)?t.map(String):[]}function tt(e){return{id:String(e.id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),enabled:Number(e.enabled)===1,branchRule:q(e.branch_rule),domainPattern:String(e.domain_pattern),ttlHours:Number(e.ttl_hours),keepCount:Number(e.keep_count),publicAccess:Number(e.public_access)===1,authenticationRequired:Number(e.authentication_required)===1,allowForks:Number(e.allow_forks)===1,inheritedSecrets:un(e.inherited_secrets),resourceOverrides:J(e.resource_overrides),databaseStrategy:String(e.database_strategy),maxMonthlyCost:Number(e.max_monthly_cost),maxCpu:Number(e.max_cpu),maxMemoryMb:Number(e.max_memory_mb),cleanupOnClose:Number(e.cleanup_on_close)===1,version:Number(e.version),createdByActorId:q(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ce(e){return{id:String(e.id),definitionId:String(e.definition_id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),identityKey:String(e.identity_key),sourceProvider:q(e.source_provider),repository:q(e.repository),branch:String(e.branch),pullRequestNumber:e.pull_request_number==null?void 0:Number(e.pull_request_number),fork:Number(e.fork)===1,commitSha:String(e.commit_sha),name:String(e.name),stackName:String(e.stack_name),url:q(e.url),status:String(e.status),expiresAt:String(e.expires_at),latestOperationId:q(e.latest_operation_id),createdByActorId:q(e.created_by_actor_id),costEstimate:e.cost_estimate==null?void 0:Number(e.cost_estimate),desiredState:J(e.desired_state),observedState:J(e.observed_state),teardownError:q(e.teardown_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),destroyedAt:q(e.destroyed_at)}}function xt(e){return{id:String(e.id),previewId:String(e.preview_id),provider:String(e.provider),providerResourceId:String(e.provider_resource_id),kind:String(e.kind),tags:J(e.tags),observedState:J(e.observed_state),discoveredAt:String(e.discovered_at),deletedAt:q(e.deleted_at)}}function V(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,Math.floor(e))):t}function Oe(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,e)):t}function rt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,28)||"preview"}class Xe{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}createDefinition(e){let t=this.controlPlane.getResource(e.resourceId),r=this.controlPlane.listEnvironments(e.projectId).find((E)=>E.id===e.baseEnvironmentId);if(!t||t.projectId!==e.projectId||t.environmentId!==r?.id)throw Error("Preview resource and base environment must belong to the same project scope");if(t.kind!=="application")throw Error("Preview environments currently support application resources only");if(!/^https:\/\//.test(e.domainPattern)||!e.domainPattern.includes("{name}"))throw Error("Preview domainPattern must be HTTPS and include {name}");let n=this.getDefinitionForResource(e.resourceId),o=e.publicAccess??n?.publicAccess??!1,a=e.authenticationRequired??n?.authenticationRequired??!0;if(o&&!a)throw Error("Public preview environments require an authentication policy");let d=[...new Set(e.inheritedSecrets??[])];if(d.some((E)=>!ln.test(E)))throw Error("Inherited preview secret names must use uppercase environment-variable identifiers");let u=this.now().toISOString();if(n)return this.controlPlane.database.run("UPDATE preview_definitions SET base_environment_id=?, enabled=1, branch_rule=?, domain_pattern=?, ttl_hours=?, keep_count=?, public_access=?, authentication_required=?, allow_forks=?, inherited_secrets=?, resource_overrides=?, database_strategy=?, max_monthly_cost=?, max_cpu=?, max_memory_mb=?, cleanup_on_close=?, version=version+1, updated_at=? WHERE id=?",[e.baseEnvironmentId,e.branchRule??null,e.domainPattern,V(e.ttlHours,n.ttlHours,1,720),V(e.keepCount,n.keepCount,1,100),o?1:0,a?1:0,e.allowForks??n.allowForks?1:0,JSON.stringify(e.inheritedSecrets===void 0?n.inheritedSecrets:d),JSON.stringify(s(e.resourceOverrides??n.resourceOverrides)),e.databaseStrategy??n.databaseStrategy,Oe(e.maxMonthlyCost,n.maxMonthlyCost,0,1e4),Oe(e.maxCpu,n.maxCpu,0.1,64),V(e.maxMemoryMb,n.maxMemoryMb,128,131072),e.cleanupOnClose??n.cleanupOnClose?1:0,u,n.id]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.updated",payload:{definitionId:n.id,baseEnvironmentId:e.baseEnvironmentId,version:n.version+1}}),this.getDefinition(n.id);let p=this.id();return this.controlPlane.database.run("INSERT INTO preview_definitions (id, project_id, resource_id, base_environment_id, enabled, branch_rule, domain_pattern, ttl_hours, keep_count, public_access, authentication_required, allow_forks, inherited_secrets, resource_overrides, database_strategy, max_monthly_cost, max_cpu, max_memory_mb, cleanup_on_close, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[p,e.projectId,e.resourceId,e.baseEnvironmentId,e.branchRule??null,e.domainPattern,V(e.ttlHours,24,1,720),V(e.keepCount,10,1,100),e.publicAccess?1:0,e.authenticationRequired===!1?0:1,e.allowForks?1:0,JSON.stringify(d),JSON.stringify(s(e.resourceOverrides??{})),e.databaseStrategy??"disabled",Oe(e.maxMonthlyCost,25,0,1e4),Oe(e.maxCpu,1,0.1,64),V(e.maxMemoryMb,1024,128,131072),e.cleanupOnClose===!1?0:1,e.createdByActorId??null,u,u]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.created",payload:{definitionId:p,baseEnvironmentId:e.baseEnvironmentId,ttlHours:V(e.ttlHours,24,1,720),inheritedSecretNames:d}}),this.getDefinition(p)}getDefinition(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE id=?").get(e);return t?tt(t):void 0}getDefinitionForResource(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE resource_id=?").get(e);return t?tt(t):void 0}listDefinitions(e){return this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE project_id=? ORDER BY updated_at DESC").all(e).map(tt)}listInstances(e={}){return this.controlPlane.database.query("SELECT * FROM preview_instances ORDER BY created_at DESC").all().map(ce).filter((r)=>(!e.projectId||r.projectId===e.projectId)&&(!e.definitionId||r.definitionId===e.definitionId)&&(!e.status||r.status===e.status))}getInstance(e){let t=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE id=?").get(e);return t?ce(t):void 0}findForPullRequest(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`pr:${t}:${r}`);return n?ce(n):void 0}findForBranch(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`branch:${t}:${r}`);return n?ce(n):void 0}upsert(e){let t=this.getDefinition(e.definitionId);if(!t?.enabled)throw Error("Preview environments are not enabled for this application");if(!dn.test(e.commitSha))throw Error("Preview deployment requires an immutable 40-64 character commit SHA");if(e.fork&&!t.allowForks)throw Error("Untrusted fork previews are disabled");let r=e.pullRequestNumber?`pr:${e.repository??"unknown"}:${e.pullRequestNumber}`:`branch:${e.repository??"local"}:${e.branch}`,n=an("sha256").update(`${t.id}:${r}`).digest("hex").slice(0,8),a=`${(e.pullRequestNumber?`pr-${e.pullRequestNumber}`:rt(e.branch)).slice(0,28)}-${n}`,d=`preview-${a}`.slice(0,63),u=t.domainPattern.replaceAll("{name}",a).replaceAll("{project}",rt(t.projectId)).replaceAll("{branch}",rt(e.branch)).replaceAll("{pr}",String(e.pullRequestNumber??"branch")),p=e.now??this.now(),E=p.toISOString(),g=new Date(p.getTime()+t.ttlHours*60*60*1000).toISOString(),m=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(t.id,r);if(m){let _=ce(m),N=_.commitSha!==e.commitSha||_.status==="destroyed";if(N)this.controlPlane.database.run("UPDATE preview_instances SET commit_sha=?, branch=?, fork=?, status='queued', expires_at=?, url=?, teardown_error=NULL, destroyed_at=NULL, version=version+1, updated_at=? WHERE id=?",[e.commitSha,e.branch,e.fork?1:0,g,u,E,_.id]);return{preview:this.getInstance(_.id),created:!1,changed:N,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}let T=this.id(),h=s({source:{provider:e.sourceProvider??null,repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:!!e.fork},policy:{databaseStrategy:t.databaseStrategy,resourceOverrides:t.resourceOverrides,maxMonthlyCost:t.maxMonthlyCost,maxCpu:t.maxCpu,maxMemoryMb:t.maxMemoryMb,publicAccess:t.publicAccess,authenticationRequired:t.authenticationRequired},inheritedSecretNames:e.fork?[]:t.inheritedSecrets});return this.controlPlane.database.run("INSERT INTO preview_instances (id, definition_id, project_id, resource_id, base_environment_id, identity_key, source_provider, repository, branch, pull_request_number, fork, commit_sha, name, stack_name, url, status, expires_at, created_by_actor_id, desired_state, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'queued', ?, ?, ?, ?, ?)",[T,t.id,t.projectId,t.resourceId,t.baseEnvironmentId,r,e.sourceProvider??null,e.repository??null,e.branch,e.pullRequestNumber??null,e.fork?1:0,e.commitSha,a,d,u,g,e.createdByActorId??null,JSON.stringify(h),E,E]),this.controlPlane.appendEvent({projectId:t.projectId,resourceId:t.resourceId,actorId:e.createdByActorId,type:"preview.created",payload:{previewId:T,identityKey:r,commitSha:e.commitSha,expiresAt:g,fork:!!e.fork}}),{preview:this.getInstance(T),created:!0,changed:!0,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}transition(e,t,r={}){let n=this.getInstance(e);if(!n)throw Error(`Preview ${e} was not found`);let o=this.now().toISOString(),a=t==="destroyed"?o:null;return this.controlPlane.database.run("UPDATE preview_instances SET status=?, latest_operation_id=COALESCE(?, latest_operation_id), observed_state=?, teardown_error=?, cost_estimate=COALESCE(?, cost_estimate), destroyed_at=?, version=version+1, updated_at=? WHERE id=?",[t,r.operationId??null,JSON.stringify(s(r.observedState??n.observedState)),r.teardownError??null,r.costEstimate??null,a,o,e]),this.controlPlane.appendEvent({projectId:n.projectId,resourceId:n.resourceId,operationId:r.operationId,type:`preview.${t}`,level:t==="failed"||t==="cleanup_failed"?"error":"info",payload:{previewId:e,commitSha:n.commitSha,teardownError:r.teardownError??null}}),this.getInstance(e)}extend(e,t){let r=this.getInstance(e),n=r?this.getDefinition(r.definitionId):void 0;if(!r||!n)throw Error(`Preview ${e} was not found`);let o=this.now(),a=V(t,n.ttlHours,1,720),d=new Date(Math.max(o.getTime(),new Date(r.expiresAt).getTime())+a*3600000).toISOString();return this.controlPlane.database.run("UPDATE preview_instances SET expires_at=?, version=version+1, updated_at=? WHERE id=?",[d,o.toISOString(),e]),this.getInstance(e)}expired(e=this.now()){return this.listInstances().filter((t)=>["queued","deploying","active","updating","failed","cleanup_failed"].includes(t.status)&&new Date(t.expiresAt)<=e)}recordResource(e){let t=this.getInstance(e.previewId);if(!t)throw Error(`Preview ${e.previewId} was not found`);let r={"ts-cloud:preview":t.id,"ts-cloud:project":t.projectId,"ts-cloud:expires-at":t.expiresAt};for(let[d,u]of Object.entries(r))if(e.tags[d]!==u)throw Error(`Preview resource is missing immutable tag ${d}`);let n=this.id(),o=this.now().toISOString();this.controlPlane.database.run("INSERT INTO preview_resources (id, preview_id, provider, provider_resource_id, kind, tags, observed_state, discovered_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(preview_id, provider, provider_resource_id) DO UPDATE SET kind=excluded.kind, tags=excluded.tags, observed_state=excluded.observed_state, deleted_at=NULL",[n,t.id,e.provider,e.providerResourceId,e.kind,JSON.stringify(e.tags),JSON.stringify(s(e.observedState??{})),o]);let a=this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? AND provider=? AND provider_resource_id=?").get(t.id,e.provider,e.providerResourceId);return xt(a)}listResources(e){return this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? ORDER BY kind, provider_resource_id").all(e).map(xt)}markResourcesDeleted(e){if(!this.getInstance(e))throw Error(`Preview ${e} was not found`);return this.controlPlane.database.run("UPDATE preview_resources SET deleted_at=? WHERE preview_id=? AND deleted_at IS NULL",[this.now().toISOString(),e]).changes}}class Xr{controlPlane;previews;queue;constructor(e){this.controlPlane=e;this.previews=new Xe(e),this.queue=new c(e)}enqueueDeploy(e,t={}){let r=t.created?"preview.create":"preview.update",n=t.reason==="manual_rebuild"?`:${crypto.randomUUID()}`:"",o=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:t.actorId,kind:r,correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:${e.commitSha}${n}`,input:{previewId:e.id,reason:t.reason??(t.created?"create":"commit_update"),source:{repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:e.fork}},lockKey:`preview:${e.id}`,providerKey:"preview",buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:o.id}),o}enqueueDestroy(e,t,r){if(e.status==="destroyed")throw Error("Preview is already destroyed");let n=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:r,kind:"preview.destroy",correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:destroy:${t}`,input:{previewId:e.id,reason:t},lockKey:`preview:${e.id}`,providerKey:"preview",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:n.id}),n}cleanup(e={}){let t=e.now??new Date,r=new Map,n=this.previews.listInstances().filter((p)=>!["destroyed","destroying"].includes(p.status)),o=(p,E)=>{let g=r.get(p.id)??{preview:p,reasons:[]};if(!g.reasons.includes(E))g.reasons.push(E);r.set(p.id,g)};for(let p of n){if(new Date(p.expiresAt)<=t)o(p,"ttl_expired");if(e.maxAgeHours&&t.getTime()-new Date(p.createdAt).getTime()>=e.maxAgeHours*3600000)o(p,"max_age")}let a=new Map;for(let p of n)a.set(p.definitionId,[...a.get(p.definitionId)??[],p]);for(let[p,E]of a){let g=this.previews.getDefinition(p),m=e.keepCount??g?.keepCount;if(!m)continue;E.sort((T,h)=>h.createdAt.localeCompare(T.createdAt)).slice(m).forEach((T)=>o(T,"keep_count"))}let d=[...r.values()].sort((p,E)=>p.preview.createdAt.localeCompare(E.preview.createdAt)),u=e.dryRun?[]:d.map((p)=>this.enqueueDestroy(p.preview,p.reasons.sort().join("+"),e.actorId));if(d.length)this.controlPlane.appendEvent({actorId:e.actorId,type:e.dryRun?"preview.cleanup.planned":"preview.cleanup.queued",payload:{previewIds:d.map((p)=>p.preview.id),reasons:Object.fromEntries(d.map((p)=>[p.preview.id,p.reasons])),dryRun:!!e.dryRun}});return{candidates:d,operations:u,dryRun:!!e.dryRun}}reconcile(e){let t=[],r=[],n=[];for(let o of e){let a=o.tags["ts-cloud:preview"],d=o.tags["ts-cloud:project"],u=o.tags["ts-cloud:expires-at"];if(!a||!d||!u){n.push(o.providerResourceId);continue}let p=this.previews.getInstance(a);if(!p||p.projectId!==d||p.expiresAt!==u){r.push(o.providerResourceId);continue}if(this.previews.recordResource({...o,previewId:p.id}),o.estimatedMonthlyCost!==void 0)this.previews.transition(p.id,p.status,{costEstimate:o.estimatedMonthlyCost,observedState:{...p.observedState,lastReconciledAt:new Date().toISOString()}});t.push(o.providerResourceId)}if(r.length)this.controlPlane.appendEvent({type:"preview.reconciliation.leaks",level:"error",payload:{providerResourceIds:r}});return{matched:t,unknownPreviewResources:r,ignoredUntagged:n}}}var kA=["deployment.create","deployment.rollback","application.create","deploy.source","deploy.preview","preview.create","preview.update","preview.destroy","compose.deploy","compose.redeploy","compose.start","compose.stop","compose.delete","compose.scale"];function Ue(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function NA(e,t){if(!t.projectId||!t.environmentId)throw Error(`Queued ${t.kind} operation is missing its project or environment scope`);let r=e.listEnvironments(t.projectId).find((d)=>d.id===t.environmentId);if(!r)throw Error(`Environment ${t.environmentId} was not found for queued ${t.kind} operation`);let n=t.resourceId?e.getResource(t.resourceId):void 0;if(t.resourceId&&(!n||n.projectId!==t.projectId||n.environmentId!==t.environmentId))throw Error(`Resource ${t.resourceId} was not found in the queued deployment scope`);let o=Ue(t.input);if(t.kind.startsWith("compose.")){let d=typeof o.applicationId==="string"?o.applicationId:void 0,u=d?new or(e).get(d):t.resourceId?new or(e).getByResource(t.resourceId):void 0;if(!u||u.projectId!==t.projectId||u.environmentId!==t.environmentId||u.resourceId!==t.resourceId)throw Error("Queued Compose application does not match the operation scope");let p=t.kind.slice(8),E=["compose:apply",u.id,"--action",p,"--env",r.slug];if(typeof o.service==="string"&&o.service)E.push("--service",o.service);if(typeof o.replicas==="number")E.push("--replicas",String(o.replicas));if(o.removeVolumes===!0)E.push("--remove-volumes");return{id:`queue:${t.id}`,label:`${p[0].toUpperCase()}${p.slice(1)} Compose application`,description:`${p} ${u.name}.`,command:E,mutates:!0,target:{environment:r.slug,resource:n?.slug,composeId:u.id}}}if(t.kind.startsWith("preview.")){let d=typeof o.previewId==="string"?o.previewId:void 0,u=d?new Xe(e).getInstance(d):void 0;if(!u)throw Error(`Preview ${d??"(missing)"} was not found for queued ${t.kind}`);if(u.projectId!==t.projectId||u.resourceId!==t.resourceId)throw Error("Queued preview does not match the operation scope");if(t.kind==="preview.destroy")return{id:`queue:${t.id}`,label:"Destroy preview",description:`Destroy ${u.name}.`,command:["stack:delete",u.stackName,"--yes"],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:u.id}};return{id:`queue:${t.id}`,label:t.kind==="preview.create"?"Create preview":"Update preview",description:`Deploy ${u.name} at ${u.commitSha}.`,command:["deploy","--stack",u.stackName,"--env",r.slug,"--yes","--skip-dns-verification",...n?["--site",n.slug]:[]],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:u.id}}}if(t.kind==="deployment.rollback"){let d=["deploy:rollback"];if(n)d.push(n.slug);if(d.push("--env",r.slug),typeof o.revision==="string"&&o.revision)d.push("--to",o.revision);return{id:`queue:${t.id}`,label:"Rollback deployment",description:`Roll back ${n?.slug??r.slug}.`,command:d,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}let a=["deploy","--env",r.slug,"--yes"];if(n)a.push("--site",n.slug);return{id:`queue:${t.id}`,label:t.kind==="deploy.preview"?"Deploy preview":"Deploy release",description:`Deploy ${n?.slug??r.slug}.`,command:a,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}function pn(e){let t=e.stderr?.trim()||`Deployment process exited with code ${e.exitCode}`;if(/\b(?:429|rate.?limit|throttl)/i.test(t))return new ae(t,"provider_throttled");if(/\b(?:502|503|504|temporar(?:y|ily)|unavailable|provider.?error)/i.test(t))return new ae(t,"provider_unavailable");if(/\b(?:network|econn|enotfound|socket|timed?\s*out|fetch failed|dns)\b/i.test(t))return new ae(t,"network");return Error(t)}function Rd(e){let t=async(r)=>{r.checkpoint("prepare","Resolving the persisted deployment target.");let n=NA(e.store,r.operation),o=n.target.previewId?new Xe(e.store):void 0,a=n.target.composeId?new or(e.store):void 0;if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"destroying":r.operation.kind==="preview.update"?"updating":"deploying",{operationId:r.operation.id});if(a&&n.target.composeId)a.transition(n.target.composeId,r.operation.kind==="compose.delete"?"deleting":r.operation.kind==="compose.stop"?"stopped":"deploying",{operationId:r.operation.id});r.log(`Target: ${n.target.resource??"all resources"} in ${n.target.environment}.`,{stream:"system"}),r.throwIfCancellationRequested(),r.checkpoint("execute",`Running cloud ${n.command.join(" ")}.`);let d=await e.execute(n,r);if(!d.ok){if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"cleanup_failed":"failed",{operationId:r.operation.id,teardownError:r.operation.kind==="preview.destroy"?d.stderr?.trim()||`Process exited with ${d.exitCode}`:void 0});if(a&&n.target.composeId)a.transition(n.target.composeId,r.operation.kind==="compose.delete"?"degraded":"failed",{operationId:r.operation.id,error:d.stderr?.trim()||`Process exited with ${d.exitCode}`});throw pn(d)}if(r.throwIfCancellationRequested(),o&&n.target.previewId){let u=o.getInstance(n.target.previewId);if(r.operation.kind==="preview.destroy")o.markResourcesDeleted(u.id),o.transition(u.id,"destroyed",{operationId:r.operation.id,observedState:{reconciledResourceIds:o.listResources(u.id).map((p)=>p.providerResourceId),exactCommitSha:u.commitSha}});else{let p=e.store.getResource(u.resourceId)?.provider??"default";o.recordResource({previewId:u.id,provider:p,providerResourceId:u.stackName,kind:"stack",tags:{"ts-cloud:preview":u.id,"ts-cloud:project":u.projectId,"ts-cloud:expires-at":u.expiresAt},observedState:{command:d.command??null,exactCommitSha:u.commitSha}}),o.transition(u.id,"active",{operationId:r.operation.id,observedState:{url:u.url??null,stackName:u.stackName,exactCommitSha:u.commitSha,providerStatus:"deployed"}})}}if(a&&n.target.composeId){let u=a.get(n.target.composeId),p=typeof Ue(r.operation.input).service==="string"?String(Ue(r.operation.input).service):void 0,E=r.operation.kind==="compose.delete"?"deleted":r.operation.kind==="compose.stop"?"stopped":"running",g=a.transition(u.id,E,{operationId:r.operation.id,services:Object.values(u.manifest.spec.services).filter((m)=>!p||m.name===p).map((m)=>({name:m.name,status:E==="stopped"||E==="deleted"?"stopped":"running",replicas:E==="deleted"?0:m.replicas,healthyReplicas:E==="running"?m.replicas:0,observedState:{command:d.command??null,healthGatePassed:E==="running"}}))});if(E==="deleted")Jp(e.store,g,Ue(r.operation.input).removeVolumes===!0)}return r.checkpoint("finalize","Deployment command completed; persisting the terminal result."),{command:d.command??`cloud ${n.command.join(" ")}`,exitCode:d.exitCode,environment:n.target.environment,resource:n.target.resource??null}};return Object.fromEntries(kA.map((r)=>[r,t]))}var nt=/^[a-z0-9][a-z0-9_.-]{1,62}$/,En=/^0?[0-7]{3}$/,mn=["/","/boot","/dev","/etc","/proc","/root","/run","/sys","/var/run","/var/lib/docker","/var/lib/containers"],Tn=["create","attach","detach","resize","snapshot","restore","delete","adopt","usage"],gn=(e)=>e&&typeof e==="object"&&!Array.isArray(e)?e:{};function BA(e){return Object.fromEntries(Tn.map((t)=>[t,{supported:!1,reason:e}]))}function Eo(e,t={}){let r=BA("This storage driver does not support the operation.");for(let n of e)r[n]={supported:!0};return{...r,...t}}function xA(e){if(!e.startsWith("/")||e.includes("\x00")||e.split("/").includes(".."))throw Error("Mount target must be an absolute normalized path without traversal.");let t=e.replace(/\/+$/,"")||"/";if(mn.some((r)=>t===r||t.startsWith(`${r}/`)))throw Error(`Mount target ${e} is a protected host or runtime path.`)}function OA(e){if(xA(e.targetPath),e.uid!=null&&(!Number.isInteger(e.uid)||e.uid<0))throw Error("Mount UID must be a non-negative integer.");if(e.gid!=null&&(!Number.isInteger(e.gid)||e.gid<0))throw Error("Mount GID must be a non-negative integer.");if(e.mode&&!En.test(e.mode))throw Error("Mount mode must be a three or four digit octal value.");if(e.propagation&&!["private","rprivate","shared","rshared","slave","rslave"].includes(e.propagation))throw Error("Unsupported mount propagation mode.")}class vo{store;drivers;now;queue;constructor(e,t,r,n=()=>new Date){this.store=e;this.drivers=t;this.now=n;this.queue=r??new c(e.controlPlane)}driver(e,t){let r=this.drivers.find((n)=>n.provider===e&&n.type===t);if(!r)throw Error(`No ${e} ${t} volume driver is configured.`);return r}capability(e,t){let r=e.capabilities[t];if(!r?.supported)throw Error(r?.reason??`${t} is unsupported for this volume.`)}queueMutation(e,t,r,n,o){return this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:o??e.resourceId,actorId:n,kind:t,idempotencyKey:`${t}:${e.id}:v${e.version}:${JSON.stringify(r)}`,correlationId:`volume:${e.id}`,input:{volumeId:e.id,...r},lockKey:o?`resource:${o}`:`volume:${e.id}`,providerKey:e.provider,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:365}).operation}create(e){if(!nt.test(e.name))throw Error("Volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");if(e.capacityBytes!=null&&(!Number.isSafeInteger(e.capacityBytes)||e.capacityBytes<=0))throw Error("Volume capacity must be a positive byte count.");let t=this.store.controlPlane.getProject(e.projectId),r=e.environmentId?this.store.controlPlane.listEnvironments(e.projectId).find((E)=>E.id===e.environmentId):void 0,n=e.resourceId?this.store.controlPlane.getResource(e.resourceId):void 0;if(!t||t.organizationId!==e.organizationId)throw Error("Volume project does not belong to the organization.");if(e.environmentId&&!r)throw Error("Volume environment does not belong to the project.");if(n&&(n.projectId!==e.projectId||n.environmentId!==e.environmentId||n.kind!=="volume"))throw Error("Volume resource does not belong to the selected scope.");let o=n??this.store.controlPlane.createResource({projectId:e.projectId,environmentId:e.environmentId,kind:"volume",slug:e.name,name:e.name,provider:e.provider,desiredState:{type:e.type,capacityBytes:e.capacityBytes??null,filesystem:e.filesystem??null,encrypted:!!e.encrypted}}),a=this.driver(e.provider,e.type),d=a.capabilities(),u=this.store.create({organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,resourceId:o.id,name:e.name,provider:e.provider,type:e.type,status:"pending",capacityBytes:e.capacityBytes,filesystem:e.filesystem,encrypted:!!e.encrypted,capabilities:d,desiredState:e.desiredState??{},observedState:{}}),p=this.queueMutation(u,"volume.create",{},e.actorId);return this.store.audit({organizationId:u.organizationId,projectId:u.projectId,environmentId:u.environmentId,actorId:e.actorId,type:"volume.create.queued",volumeId:u.id,payload:{name:u.name,type:u.type}}),{volume:u,operation:p}}attach(e,t){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"attach"),OA(t);let n=this.store.controlPlane.getResource(t.resourceId);if(!n||n.projectId!==r.projectId||n.environmentId!==r.environmentId)throw Error("Cross-project or cross-environment volume attachments are forbidden.");let o=this.store.upsertAttachment({volumeId:e,resourceId:t.resourceId,targetPath:t.targetPath,readOnly:!!t.readOnly,uid:t.uid,gid:t.gid,mode:t.mode,propagation:t.propagation??"private",driverOptions:t.driverOptions??{},desiredState:"attached",observedState:"pending"}),a=this.queueMutation(r,"volume.attach",{attachmentId:o.id},t.actorId,t.resourceId);return this.store.updateAttachment(o.id,{operationId:a.id}),this.store.update(r.id,r.version,{status:"attaching"}),this.store.audit({organizationId:r.organizationId,projectId:r.projectId,environmentId:r.environmentId,actorId:t.actorId,type:"volume.attach.queued",volumeId:e,payload:{resourceId:t.resourceId,targetPath:t.targetPath}}),{volume:this.store.get(r.id),attachment:this.store.attachment(o.id),operation:a}}detach(e,t,r={}){let n=this.store.get(e),o=this.store.attachment(t);if(!n||!o||o.volumeId!==e)throw Error("Volume attachment was not found.");if(this.capability(n,"detach"),o.observedState==="attached"&&(!r.drained||!r.unmounted))throw Error("Detach requires completed workload drain and filesystem unmount checkpoints.");if(r.force&&r.confirmation!==`detach ${n.name}`)throw Error(`Force detach requires confirmation: detach ${n.name}`);let a=this.store.updateAttachment(t,{desiredState:"detached"}),d=this.queueMutation(n,"volume.detach",{attachmentId:t,force:!!r.force},r.actorId,o.resourceId);return this.store.updateAttachment(t,{operationId:d.id}),this.store.update(n.id,n.version,{status:"detaching"}),{volume:this.store.get(e),attachment:a,operation:d}}resize(e,t,r={}){let n=this.store.get(e);if(!n)throw Error("Volume was not found.");if(this.capability(n,"resize"),!Number.isSafeInteger(t)||t<=0)throw Error("Volume capacity must be a positive byte count.");if(n.capacityBytes!=null&&t<n.capacityBytes)throw Error("Volume shrinking is not supported because it can corrupt data.");let o=n.capabilities.resize;if(o.minimumBytes&&t<o.minimumBytes)throw Error(`Minimum supported capacity is ${o.minimumBytes} bytes.`);if(o.maximumBytes&&t>o.maximumBytes)throw Error(`Maximum supported capacity is ${o.maximumBytes} bytes.`);if(o.online===!1&&!r.drained)throw Error("This resize requires a completed workload drain checkpoint.");let a=this.store.update(e,n.version,{status:"resizing",desiredState:{...n.desiredState,capacityBytes:t}}),d=this.queueMutation(a,"volume.resize",{capacityBytes:t},r.actorId);return{volume:a,operation:d}}snapshot(e,t={}){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"snapshot");let n=this.store.createSnapshot({volumeId:e,name:t.name??`${r.name}-${this.now().toISOString().replace(/[:.]/g,"-")}`,status:"pending",encrypted:r.encrypted,metadata:{}}),o=this.store.update(e,r.version,{status:"snapshotting"}),a=this.queueMutation(o,"volume.snapshot",{snapshotId:n.id},t.actorId);return{volume:o,snapshot:n,operation:a}}restore(e,t){let r=this.store.snapshot(e),n=r?this.store.get(r.volumeId):void 0;if(!r||!n||r.status!=="available")throw Error("An available volume snapshot is required for restore.");if(this.capability(n,"restore"),!nt.test(t.name))throw Error("Restored volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");let o=this.store.controlPlane.createResource({projectId:n.projectId,environmentId:n.environmentId,kind:"volume",slug:t.name,name:t.name,provider:n.provider,desiredState:{restoreFromSnapshotId:r.id}}),a=this.store.create({organizationId:n.organizationId,projectId:n.projectId,environmentId:n.environmentId,resourceId:o.id,name:t.name,provider:n.provider,type:n.type,status:"pending",capacityBytes:r.sizeBytes??n.capacityBytes,filesystem:n.filesystem,encrypted:r.encrypted,capabilities:n.capabilities,desiredState:{restoreFromSnapshotId:r.id,sourceVolumeId:n.id},observedState:{}}),d=this.queueMutation(a,"volume.restore",{snapshotId:r.id,sourceVolumeId:n.id},t.actorId);return{volume:a,snapshot:r,operation:d}}delete(e,t){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"delete");let n=this.store.attachments(e).filter((u)=>u.desiredState==="attached"||u.observedState==="attached");if(n.length)throw Error(`Detach ${n.length} active consumer(s) before deleting this volume.`);if(!t.recentAuthAt||this.now().getTime()-new Date(t.recentAuthAt).getTime()>900000)throw Error("Volume deletion requires authentication verified within the last 15 minutes.");if(t.confirmation!==r.name)throw Error(`Type ${r.name} to confirm permanent volume deletion.`);if(!(r.lastBackupAt&&this.now().getTime()-new Date(r.lastBackupAt).getTime()<=86400000)&&(!t.backupOverride||t.backupOverrideConfirmation!==`delete without backup ${r.name}`))throw Error(`A verified backup from the last 24 hours is required, or confirm: delete without backup ${r.name}`);let a=this.store.update(e,r.version,{status:"deleting"}),d=this.queueMutation(a,"volume.delete",{backupOverride:!!t.backupOverride},t.actorId);return{volume:a,operation:d}}async discover(e){let t=new Set;for(let r of this.drivers)for(let n of await r.discover(e.projectId,e.environmentId)){let o=this.store.list({projectId:e.projectId,environmentId:e.environmentId}).find((d)=>d.provider===r.provider&&d.providerId===n.providerId);if(o){t.add(o.id),this.store.update(o.id,o.version,{capacityBytes:n.capacityBytes,usedBytes:n.usedBytes,filesystem:n.filesystem,encrypted:n.encrypted??o.encrypted,observedState:n.raw??{},status:o.status==="orphaned"?"available":o.status,orphanedAt:void 0});continue}let a=this.store.create({organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,name:`orphan-${n.providerId}`.toLowerCase().replace(/[^a-z0-9_.-]/g,"-").slice(0,63),provider:r.provider,providerId:n.providerId,type:r.type,status:"orphaned",capacityBytes:n.capacityBytes,usedBytes:n.usedBytes,filesystem:n.filesystem,encrypted:!!n.encrypted,capabilities:r.capabilities(),desiredState:{},observedState:n.raw??{},orphanedAt:this.now().toISOString()});t.add(a.id)}return this.store.list({projectId:e.projectId,environmentId:e.environmentId})}adopt(e,t){let r=this.store.get(e);if(!r||r.status!=="orphaned")throw Error("Only discovered orphan volumes can be adopted.");if(!nt.test(t.name))throw Error("Volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");let n=this.store.update(e,r.version,{name:t.name,status:"available",adoptedAt:this.now().toISOString(),orphanedAt:void 0});return this.store.audit({organizationId:r.organizationId,projectId:r.projectId,environmentId:r.environmentId,actorId:t.actorId,type:"volume.adopted",volumeId:e,payload:{providerId:r.providerId??null}}),n}}function _n(e){let t=gn(e.input);if(typeof t.volumeId!=="string")throw Error("Queued volume operation is missing its volume identity.");return{volumeId:t.volumeId,sourceVolumeId:typeof t.sourceVolumeId==="string"?t.sourceVolumeId:void 0,attachmentId:typeof t.attachmentId==="string"?t.attachmentId:void 0,snapshotId:typeof t.snapshotId==="string"?t.snapshotId:void 0,capacityBytes:typeof t.capacityBytes==="number"?t.capacityBytes:void 0,force:t.force===!0}}function Dd(e,t){let r=(o)=>{let a=t.find((d)=>d.provider===o.provider&&d.type===o.type);if(!a)throw Error(`No ${o.provider} ${o.type} volume driver is configured.`);return a},n=async(o)=>{let a=_n(o.operation),d=e.get(a.volumeId);if(!d)throw Error("Queued volume was not found.");let u=r(d);o.checkpoint("preflight","Validating persistent volume identity and capabilities."),o.throwIfCancellationRequested();let p;if(o.operation.kind==="volume.create")p=await u.create(d),e.update(d.id,d.version,{providerId:p.providerId,capacityBytes:p.capacityBytes??d.capacityBytes,usedBytes:p.usedBytes,filesystem:p.filesystem??d.filesystem,encrypted:p.encrypted??d.encrypted,observedState:p.raw??{},status:"available"});else if(o.operation.kind==="volume.attach"){let E=a.attachmentId?e.attachment(a.attachmentId):void 0;if(!E)throw Error("Queued volume attachment was not found.");await u.attach(d,E),e.updateAttachment(E.id,{observedState:"attached",lastError:void 0}),e.update(d.id,d.version,{status:"attached"})}else if(o.operation.kind==="volume.detach"){let E=a.attachmentId?e.attachment(a.attachmentId):void 0;if(!E)throw Error("Queued volume attachment was not found.");await u.detach(d,E,{force:a.force}),e.updateAttachment(E.id,{observedState:"detached",lastError:void 0});let g=e.attachments(d.id).some((m)=>m.id!==E.id&&m.observedState==="attached");e.update(d.id,d.version,{status:g?"attached":"available"})}else if(o.operation.kind==="volume.resize"){if(!a.capacityBytes)throw Error("Queued volume resize is missing its capacity.");p=await u.resize(d,a.capacityBytes),e.update(d.id,d.version,{capacityBytes:p.capacityBytes??a.capacityBytes,usedBytes:p.usedBytes??d.usedBytes,observedState:p.raw??d.observedState,status:e.attachments(d.id).some((E)=>E.observedState==="attached")?"attached":"available"})}else if(o.operation.kind==="volume.snapshot"){let E=a.snapshotId?e.snapshot(a.snapshotId):void 0;if(!E)throw Error("Queued volume snapshot was not found.");let g=await u.snapshot(d,E);e.updateSnapshot(E.id,{...g,status:"available"}),e.update(d.id,d.version,{status:e.attachments(d.id).some((m)=>m.observedState==="attached")?"attached":"available",lastBackupAt:new Date().toISOString()})}else if(o.operation.kind==="volume.restore"){let E=a.snapshotId?e.snapshot(a.snapshotId):void 0,g=a.sourceVolumeId?e.get(a.sourceVolumeId):void 0;if(!E||!g)throw Error("Queued volume restore source was not found.");p=await u.restore(g,E,d),e.update(d.id,d.version,{providerId:p.providerId,capacityBytes:p.capacityBytes??d.capacityBytes,usedBytes:p.usedBytes,filesystem:p.filesystem??d.filesystem,encrypted:p.encrypted??d.encrypted,observedState:p.raw??{},status:"available"})}else if(o.operation.kind==="volume.delete")await u.delete(d),e.update(d.id,d.version,{status:"deleted",deletedAt:new Date().toISOString()});return o.checkpoint("finalize","Persisted observed volume state."),{volumeId:d.id,status:e.get(d.id)?.status??"deleted"}};return Object.fromEntries(["volume.create","volume.attach","volume.detach","volume.resize","volume.snapshot","volume.restore","volume.delete"].map((o)=>[o,n]))}var vn=async(e)=>{let t=Bun.spawn(["docker",...e],{stdout:"pipe",stderr:"pipe"}),[r,n,o]=await Promise.all([t.exited,new Response(t.stdout).text(),new Response(t.stderr).text()]);return{code:r,stdout:n,stderr:o}},Z=/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/;class Yr{command;provider="docker";type="docker";constructor(e=vn){this.command=e}capabilities(){return Eo(["create","attach","detach","delete","adopt","usage"],{resize:{supported:!1,reason:"Docker named volumes do not expose a portable capacity resize operation."},snapshot:{supported:!1,reason:"Attach a volume backup policy to create verified recovery points."},restore:{supported:!1,reason:"Restore this volume from its verified backup recovery point."}})}async run(e,t=!1){let r=await this.command(e);if(r.code!==0&&!t)throw Error(`Docker volume command failed: ${r.stderr.trim()||r.code}`);return r.stdout}async inspect(e){let t=await this.run(["volume","inspect",e],!0);if(!t.trim())return;let r;try{r=JSON.parse(t)[0]}catch{return}return{providerId:String(r.Name??e),raw:{driver:String(r.Driver??"local"),mountpoint:String(r.Mountpoint??""),labels:r.Labels??{}}}}async discover(e,t){let r=await this.run(["volume","ls","--format","{{.Name}}"]),n=[];for(let o of r.split(`
1565
+ [output truncated]`;let p=this.idFn(),E=this.now();return this.controlPlane.database.run("INSERT INTO operation_logs (id, operation_id, stream, step, message, redacted, truncated, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",[p,e,r.stream??"stdout",r.step??null,n,o?1:0,u?1:0,E]),kt(this.controlPlane.database.query("SELECT * FROM operation_logs WHERE id=?").get(p))}logs(e,t={}){let r=Math.min(1000,Math.max(1,t.limit??200));return this.controlPlane.database.query("SELECT * FROM operation_logs WHERE operation_id=? AND sequence>? ORDER BY sequence ASC LIMIT ?").all(e,t.after??0,r).map(kt)}requestCancellation(e,t){let r=this.controlPlane.getOperation(e);if(!r||$r.includes(r.state))throw Error("Only queued or running operations can be cancelled");let n=this.controlPlane.requestCancellation(e);if(this.controlPlane.appendEvent({projectId:r.projectId,operationId:e,resourceId:r.resourceId,actorId:t,correlationId:r.correlationId,type:"operation.cancellation_requested",level:"warning",payload:{state:r.state}}),this.appendLog(e,r.state==="queued"?"Cancellation accepted before execution.":"Cancellation requested; waiting for the current provider step.",{stream:"system"}),n.state==="queued")return this.finish(e,"cancelled",{cancelledBeforeStart:!0});return n}retry(e,t,r={}){let n=this.controlPlane.getOperation(e),o=this.getJob(e);if(!n||!o||!["failed","cancelled","timed_out"].includes(n.state))throw Error("Only failed, cancelled, or timed-out queue jobs can be retried");if(n.attempt>=o.maxAttempts)throw Error(`Operation reached its ${o.maxAttempts}-attempt limit`);if(!o.retryClasses.includes(t))throw Error(`Retry class ${t} is not allowed for this operation`);let a=this.controlPlane.transitionOperation(e,{to:"queued",expectedVersion:n.version,error:`Retry requested after ${t}`}),d=new Date(this.nowFn().getTime()+Math.max(0,r.delayMs??0)).toISOString();this.controlPlane.database.run("UPDATE operations SET cancel_requested_at=NULL, finished_at=NULL WHERE id=?",[e]),this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason=NULL, updated_at=? WHERE operation_id=?",[d,this.now(),e]),this.controlPlane.appendEvent({projectId:n.projectId,operationId:e,resourceId:n.resourceId,actorId:r.actorId,correlationId:n.correlationId,type:"operation.retry_requested",payload:{errorClass:t,availableAt:d,nextAttempt:n.attempt+1}}),this.appendLog(e,`Retry queued for error class ${t}.`,{stream:"system"});let u=this.controlPlane.getOperation(a.id);return this.notifyAvailable(),u}release(e){this.controlPlane.database.run("DELETE FROM operation_locks WHERE operation_id=?",[e])}finish(e,t,r={},n){let o=this.controlPlane.getOperation(e);if(!o)throw Error(`Operation ${e} was not found`);let a=this.controlPlane.transitionOperation(e,{to:t,expectedVersion:o.version,output:r,error:n});return this.release(e),a}complete(e,t={}){let r=this.controlPlane.getOperation(e);if(!r||r.state!=="running"||r.leaseOwner!==this.workerId)throw Error("Only the lease owner can complete a running operation");return this.appendLog(e,"Operation completed successfully.",{stream:"system"}),this.finish(e,"succeeded",t)}fail(e,t,r={}){let n=this.controlPlane.getOperation(e);if(!n||n.state!=="running"||n.leaseOwner!==this.workerId)throw Error("Only the lease owner can fail a running operation");return this.appendLog(e,t,{stream:"stderr"}),this.finish(e,"failed",r,t)}async runOne(e){let t=this.claimNext(Object.keys(e));if(!t)return{handled:!1};let{operation:r,job:n}=t,o=e[r.kind];if(!o)return{handled:!1};let a=new AbortController,d=!1,u=setTimeout(()=>{d=!0,a.abort(new bo(n.timeoutSeconds))},n.timeoutSeconds*1000),p=setInterval(()=>{try{this.heartbeat(r.id)}catch{}},Math.max(250,Math.floor(this.leaseMs/3))),E=setInterval(()=>{if(this.controlPlane.getOperation(r.id)?.cancelRequestedAt)a.abort(new $i)},100),g={operation:r,signal:a.signal,log:(m,T)=>this.appendLog(r.id,m,T),checkpoint:(m,T)=>{this.heartbeat(r.id,m),this.appendLog(r.id,T??m,{stream:"step",step:m})},heartbeat:()=>this.heartbeat(r.id),cancellationRequested:()=>!!this.controlPlane.getOperation(r.id)?.cancelRequestedAt,throwIfCancellationRequested:()=>{if(this.controlPlane.getOperation(r.id)?.cancelRequestedAt)throw new $i}};try{let m=await Promise.race([o(g),new Promise((_,N)=>a.signal.addEventListener("abort",()=>N(a.signal.reason),{once:!0}))]);if(this.controlPlane.getOperation(r.id).cancelRequestedAt){let _=n.cancellationMode==="provider_non_cancellable";return this.appendLog(r.id,_?"Provider step completed after cancellation was requested; reconciliation is required.":"Operation cancelled cooperatively.",{stream:"system"}),{handled:!0,operation:this.finish(r.id,"cancelled",{providerCompleted:_,reconciliationRequired:_}),terminalState:"cancelled"}}return{handled:!0,operation:this.complete(r.id,m??{}),terminalState:"succeeded"}}catch(m){if(d||m instanceof bo)return this.appendLog(r.id,`Timed out after ${n.timeoutSeconds}s.`,{stream:"system"}),{handled:!0,operation:this.finish(r.id,"timed_out",{reconciliationRequired:n.cancellationMode==="provider_non_cancellable"},m instanceof Error?m.message:String(m)),terminalState:"timed_out"};if(m instanceof $i||this.controlPlane.getOperation(r.id)?.cancelRequestedAt)return{handled:!0,operation:this.finish(r.id,"cancelled",{cooperativelyCancelled:!0}),terminalState:"cancelled"};if(m instanceof ce&&n.retryClasses.includes(m.errorClass)&&r.attempt<n.maxAttempts){let _=this.controlPlane.getOperation(r.id);this.controlPlane.transitionOperation(r.id,{to:"queued",expectedVersion:_.version,error:m.message});let N=Math.min(60000,1000*2**Math.max(0,r.attempt-1)),y=new Date(this.nowFn().getTime()+N).toISOString();return this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason=?, updated_at=? WHERE operation_id=?",[y,`retry_backoff:${m.errorClass}`,this.now(),r.id]),this.release(r.id),this.appendLog(r.id,`Retryable ${m.errorClass} failure; next attempt is delayed.`,{stream:"system"}),{handled:!0,operation:this.controlPlane.getOperation(r.id),requeued:!0}}let T=m instanceof Error?m.message:String(m);return this.appendLog(r.id,T,{stream:"stderr"}),{handled:!0,operation:this.finish(r.id,"failed",{},T),terminalState:"failed"}}finally{clearTimeout(u),clearInterval(p),clearInterval(E)}}recoverExpired(){let e=this.controlPlane.database.query("SELECT o.id FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND (o.lease_expires_at IS NULL OR o.lease_expires_at<=?)").all(this.now()),t={requeued:0,failed:0,cancelled:0};for(let r of e){let n=this.controlPlane.getOperation(String(r.id)),o=this.getJob(n.id);if(this.release(n.id),n.cancelRequestedAt){this.finish(n.id,"cancelled",{recoveredAfterWorkerLoss:!0}),t.cancelled++;continue}if(o.resumePolicy==="requeue"&&n.attempt<o.maxAttempts)this.controlPlane.transitionOperation(n.id,{to:"queued",expectedVersion:n.version,error:"Worker lease expired; safely requeued from the last checkpoint."}),this.controlPlane.database.run("UPDATE operation_jobs SET available_at=?, blocked_reason='worker_restart', updated_at=? WHERE operation_id=?",[this.now(),this.now(),n.id]),this.appendLog(n.id,"Worker lease expired; operation requeued from its persisted checkpoint.",{stream:"system"}),t.requeued++;else this.finish(n.id,"failed",{recoverable:!0,lastCheckpoint:o.currentStep??null},"Worker lease expired; retry explicitly after reconciling provider state."),t.failed++}return t}clearCompleted(e={}){let t=this.now(),r=[t],n=e.projectId?"AND o.project_id=?":"";if(e.projectId)r.push(e.projectId);let o=e.before?"AND o.finished_at<=?":"";if(e.before)r.push(new Date(e.before).toISOString());let a=this.controlPlane.database.query(`SELECT o.id, o.project_id, o.correlation_id FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state IN ('succeeded','failed','cancelled','timed_out') AND j.retention_until<=? ${n} ${o}`).all(...r);for(let d of a)this.controlPlane.appendEvent({projectId:Y(d.project_id),actorId:e.actorId,correlationId:String(d.correlation_id),type:"queue.history.cleared",level:"warning",payload:{operationId:String(d.id),retentionCutoff:t}}),this.controlPlane.database.run("DELETE FROM operations WHERE id=?",[String(d.id)]);return a.length}}function Xt(e,t,r){if(!Number.isFinite(e))return t;return Math.min(r,Math.max(1,Math.floor(e)))}class Co{queue;handlers;parallelism;pollIntervalMs;onResult;onError;waits=new Map;nextWaitId=0;lanes=[];running=!1;unsubscribeAvailability;constructor(e,t,r={}){this.queue=e;this.handlers=t;this.parallelism=Xt(r.parallelism,4,100),this.pollIntervalMs=Xt(r.pollIntervalMs,5000,60000),this.onResult=r.onResult,this.onError=r.onError}get active(){return this.running}start(){if(this.running)return this;return this.running=!0,this.unsubscribeAvailability=this.queue.onAvailable(()=>this.wake()),this.lanes=Array.from({length:this.parallelism},(e,t)=>this.runLane(t)),this}stop(){this.running=!1,this.unsubscribeAvailability?.(),this.unsubscribeAvailability=void 0,this.wake()}wake(){for(let{resolve:e,timer:t}of this.waits.values()){if(t)clearTimeout(t);e()}this.waits.clear()}async settled(){await Promise.allSettled(this.lanes)}async drain(){let e=[];while(!0){let t=await Promise.all(Array.from({length:this.parallelism},()=>this.queue.runOne(this.handlers)));if(e.push(...t.filter((r)=>r.handled)),!t.some((r)=>r.handled))return e}}wait(e){return new Promise((t)=>{let r=++this.nextWaitId,n=e?setTimeout(()=>{this.waits.delete(r),t()},this.pollIntervalMs):void 0;n?.unref?.(),this.waits.set(r,{resolve:t,timer:n})})}async runLane(e){while(this.running){try{let t=await this.queue.runOne(this.handlers);if(!this.running)break;if(t.handled){this.onResult?.(t),this.wake();continue}}catch(t){this.onError?.(t)}await this.wait(e===0)}}}import{createHash as an}from"node:crypto";var dn=/^[a-f0-9]{40,64}$/i,ln=/^[A-Z][A-Z0-9_]{1,127}$/;function q(e){return typeof e==="string"&&e?e:void 0}function J(e){try{return JSON.parse(String(e))}catch{return{}}}function un(e){let t=J(e);return Array.isArray(t)?t.map(String):[]}function tt(e){return{id:String(e.id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),enabled:Number(e.enabled)===1,branchRule:q(e.branch_rule),domainPattern:String(e.domain_pattern),ttlHours:Number(e.ttl_hours),keepCount:Number(e.keep_count),publicAccess:Number(e.public_access)===1,authenticationRequired:Number(e.authentication_required)===1,allowForks:Number(e.allow_forks)===1,inheritedSecrets:un(e.inherited_secrets),resourceOverrides:J(e.resource_overrides),databaseStrategy:String(e.database_strategy),maxMonthlyCost:Number(e.max_monthly_cost),maxCpu:Number(e.max_cpu),maxMemoryMb:Number(e.max_memory_mb),cleanupOnClose:Number(e.cleanup_on_close)===1,version:Number(e.version),createdByActorId:q(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function de(e){return{id:String(e.id),definitionId:String(e.definition_id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),identityKey:String(e.identity_key),sourceProvider:q(e.source_provider),repository:q(e.repository),branch:String(e.branch),pullRequestNumber:e.pull_request_number==null?void 0:Number(e.pull_request_number),fork:Number(e.fork)===1,commitSha:String(e.commit_sha),name:String(e.name),stackName:String(e.stack_name),url:q(e.url),status:String(e.status),expiresAt:String(e.expires_at),latestOperationId:q(e.latest_operation_id),createdByActorId:q(e.created_by_actor_id),costEstimate:e.cost_estimate==null?void 0:Number(e.cost_estimate),desiredState:J(e.desired_state),observedState:J(e.observed_state),teardownError:q(e.teardown_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),destroyedAt:q(e.destroyed_at)}}function xt(e){return{id:String(e.id),previewId:String(e.preview_id),provider:String(e.provider),providerResourceId:String(e.provider_resource_id),kind:String(e.kind),tags:J(e.tags),observedState:J(e.observed_state),discoveredAt:String(e.discovered_at),deletedAt:q(e.deleted_at)}}function V(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,Math.floor(e))):t}function Oe(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,e)):t}function rt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,28)||"preview"}class Xe{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}createDefinition(e){let t=this.controlPlane.getResource(e.resourceId),r=this.controlPlane.listEnvironments(e.projectId).find((E)=>E.id===e.baseEnvironmentId);if(!t||t.projectId!==e.projectId||t.environmentId!==r?.id)throw Error("Preview resource and base environment must belong to the same project scope");if(t.kind!=="application")throw Error("Preview environments currently support application resources only");if(!/^https:\/\//.test(e.domainPattern)||!e.domainPattern.includes("{name}"))throw Error("Preview domainPattern must be HTTPS and include {name}");let n=this.getDefinitionForResource(e.resourceId),o=e.publicAccess??n?.publicAccess??!1,a=e.authenticationRequired??n?.authenticationRequired??!0;if(o&&!a)throw Error("Public preview environments require an authentication policy");let d=[...new Set(e.inheritedSecrets??[])];if(d.some((E)=>!ln.test(E)))throw Error("Inherited preview secret names must use uppercase environment-variable identifiers");let u=this.now().toISOString();if(n)return this.controlPlane.database.run("UPDATE preview_definitions SET base_environment_id=?, enabled=1, branch_rule=?, domain_pattern=?, ttl_hours=?, keep_count=?, public_access=?, authentication_required=?, allow_forks=?, inherited_secrets=?, resource_overrides=?, database_strategy=?, max_monthly_cost=?, max_cpu=?, max_memory_mb=?, cleanup_on_close=?, version=version+1, updated_at=? WHERE id=?",[e.baseEnvironmentId,e.branchRule??null,e.domainPattern,V(e.ttlHours,n.ttlHours,1,720),V(e.keepCount,n.keepCount,1,100),o?1:0,a?1:0,e.allowForks??n.allowForks?1:0,JSON.stringify(e.inheritedSecrets===void 0?n.inheritedSecrets:d),JSON.stringify(s(e.resourceOverrides??n.resourceOverrides)),e.databaseStrategy??n.databaseStrategy,Oe(e.maxMonthlyCost,n.maxMonthlyCost,0,1e4),Oe(e.maxCpu,n.maxCpu,0.1,64),V(e.maxMemoryMb,n.maxMemoryMb,128,131072),e.cleanupOnClose??n.cleanupOnClose?1:0,u,n.id]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.updated",payload:{definitionId:n.id,baseEnvironmentId:e.baseEnvironmentId,version:n.version+1}}),this.getDefinition(n.id);let p=this.id();return this.controlPlane.database.run("INSERT INTO preview_definitions (id, project_id, resource_id, base_environment_id, enabled, branch_rule, domain_pattern, ttl_hours, keep_count, public_access, authentication_required, allow_forks, inherited_secrets, resource_overrides, database_strategy, max_monthly_cost, max_cpu, max_memory_mb, cleanup_on_close, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[p,e.projectId,e.resourceId,e.baseEnvironmentId,e.branchRule??null,e.domainPattern,V(e.ttlHours,24,1,720),V(e.keepCount,10,1,100),e.publicAccess?1:0,e.authenticationRequired===!1?0:1,e.allowForks?1:0,JSON.stringify(d),JSON.stringify(s(e.resourceOverrides??{})),e.databaseStrategy??"disabled",Oe(e.maxMonthlyCost,25,0,1e4),Oe(e.maxCpu,1,0.1,64),V(e.maxMemoryMb,1024,128,131072),e.cleanupOnClose===!1?0:1,e.createdByActorId??null,u,u]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.created",payload:{definitionId:p,baseEnvironmentId:e.baseEnvironmentId,ttlHours:V(e.ttlHours,24,1,720),inheritedSecretNames:d}}),this.getDefinition(p)}getDefinition(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE id=?").get(e);return t?tt(t):void 0}getDefinitionForResource(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE resource_id=?").get(e);return t?tt(t):void 0}listDefinitions(e){return this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE project_id=? ORDER BY updated_at DESC").all(e).map(tt)}listInstances(e={}){return this.controlPlane.database.query("SELECT * FROM preview_instances ORDER BY created_at DESC").all().map(de).filter((r)=>(!e.projectId||r.projectId===e.projectId)&&(!e.definitionId||r.definitionId===e.definitionId)&&(!e.status||r.status===e.status))}getInstance(e){let t=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE id=?").get(e);return t?de(t):void 0}findForPullRequest(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`pr:${t}:${r}`);return n?de(n):void 0}findForBranch(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`branch:${t}:${r}`);return n?de(n):void 0}upsert(e){let t=this.getDefinition(e.definitionId);if(!t?.enabled)throw Error("Preview environments are not enabled for this application");if(!dn.test(e.commitSha))throw Error("Preview deployment requires an immutable 40-64 character commit SHA");if(e.fork&&!t.allowForks)throw Error("Untrusted fork previews are disabled");let r=e.pullRequestNumber?`pr:${e.repository??"unknown"}:${e.pullRequestNumber}`:`branch:${e.repository??"local"}:${e.branch}`,n=an("sha256").update(`${t.id}:${r}`).digest("hex").slice(0,8),a=`${(e.pullRequestNumber?`pr-${e.pullRequestNumber}`:rt(e.branch)).slice(0,28)}-${n}`,d=`preview-${a}`.slice(0,63),u=t.domainPattern.replaceAll("{name}",a).replaceAll("{project}",rt(t.projectId)).replaceAll("{branch}",rt(e.branch)).replaceAll("{pr}",String(e.pullRequestNumber??"branch")),p=e.now??this.now(),E=p.toISOString(),g=new Date(p.getTime()+t.ttlHours*60*60*1000).toISOString(),m=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(t.id,r);if(m){let _=de(m),N=_.commitSha!==e.commitSha||_.status==="destroyed";if(N)this.controlPlane.database.run("UPDATE preview_instances SET commit_sha=?, branch=?, fork=?, status='queued', expires_at=?, url=?, teardown_error=NULL, destroyed_at=NULL, version=version+1, updated_at=? WHERE id=?",[e.commitSha,e.branch,e.fork?1:0,g,u,E,_.id]);return{preview:this.getInstance(_.id),created:!1,changed:N,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}let T=this.id(),h=s({source:{provider:e.sourceProvider??null,repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:!!e.fork},policy:{databaseStrategy:t.databaseStrategy,resourceOverrides:t.resourceOverrides,maxMonthlyCost:t.maxMonthlyCost,maxCpu:t.maxCpu,maxMemoryMb:t.maxMemoryMb,publicAccess:t.publicAccess,authenticationRequired:t.authenticationRequired},inheritedSecretNames:e.fork?[]:t.inheritedSecrets});return this.controlPlane.database.run("INSERT INTO preview_instances (id, definition_id, project_id, resource_id, base_environment_id, identity_key, source_provider, repository, branch, pull_request_number, fork, commit_sha, name, stack_name, url, status, expires_at, created_by_actor_id, desired_state, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'queued', ?, ?, ?, ?, ?)",[T,t.id,t.projectId,t.resourceId,t.baseEnvironmentId,r,e.sourceProvider??null,e.repository??null,e.branch,e.pullRequestNumber??null,e.fork?1:0,e.commitSha,a,d,u,g,e.createdByActorId??null,JSON.stringify(h),E,E]),this.controlPlane.appendEvent({projectId:t.projectId,resourceId:t.resourceId,actorId:e.createdByActorId,type:"preview.created",payload:{previewId:T,identityKey:r,commitSha:e.commitSha,expiresAt:g,fork:!!e.fork}}),{preview:this.getInstance(T),created:!0,changed:!0,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}transition(e,t,r={}){let n=this.getInstance(e);if(!n)throw Error(`Preview ${e} was not found`);let o=this.now().toISOString(),a=t==="destroyed"?o:null;return this.controlPlane.database.run("UPDATE preview_instances SET status=?, latest_operation_id=COALESCE(?, latest_operation_id), observed_state=?, teardown_error=?, cost_estimate=COALESCE(?, cost_estimate), destroyed_at=?, version=version+1, updated_at=? WHERE id=?",[t,r.operationId??null,JSON.stringify(s(r.observedState??n.observedState)),r.teardownError??null,r.costEstimate??null,a,o,e]),this.controlPlane.appendEvent({projectId:n.projectId,resourceId:n.resourceId,operationId:r.operationId,type:`preview.${t}`,level:t==="failed"||t==="cleanup_failed"?"error":"info",payload:{previewId:e,commitSha:n.commitSha,teardownError:r.teardownError??null}}),this.getInstance(e)}extend(e,t){let r=this.getInstance(e),n=r?this.getDefinition(r.definitionId):void 0;if(!r||!n)throw Error(`Preview ${e} was not found`);let o=this.now(),a=V(t,n.ttlHours,1,720),d=new Date(Math.max(o.getTime(),new Date(r.expiresAt).getTime())+a*3600000).toISOString();return this.controlPlane.database.run("UPDATE preview_instances SET expires_at=?, version=version+1, updated_at=? WHERE id=?",[d,o.toISOString(),e]),this.getInstance(e)}expired(e=this.now()){return this.listInstances().filter((t)=>["queued","deploying","active","updating","failed","cleanup_failed"].includes(t.status)&&new Date(t.expiresAt)<=e)}recordResource(e){let t=this.getInstance(e.previewId);if(!t)throw Error(`Preview ${e.previewId} was not found`);let r={"ts-cloud:preview":t.id,"ts-cloud:project":t.projectId,"ts-cloud:expires-at":t.expiresAt};for(let[d,u]of Object.entries(r))if(e.tags[d]!==u)throw Error(`Preview resource is missing immutable tag ${d}`);let n=this.id(),o=this.now().toISOString();this.controlPlane.database.run("INSERT INTO preview_resources (id, preview_id, provider, provider_resource_id, kind, tags, observed_state, discovered_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(preview_id, provider, provider_resource_id) DO UPDATE SET kind=excluded.kind, tags=excluded.tags, observed_state=excluded.observed_state, deleted_at=NULL",[n,t.id,e.provider,e.providerResourceId,e.kind,JSON.stringify(e.tags),JSON.stringify(s(e.observedState??{})),o]);let a=this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? AND provider=? AND provider_resource_id=?").get(t.id,e.provider,e.providerResourceId);return xt(a)}listResources(e){return this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? ORDER BY kind, provider_resource_id").all(e).map(xt)}markResourcesDeleted(e){if(!this.getInstance(e))throw Error(`Preview ${e} was not found`);return this.controlPlane.database.run("UPDATE preview_resources SET deleted_at=? WHERE preview_id=? AND deleted_at IS NULL",[this.now().toISOString(),e]).changes}}class Xr{controlPlane;previews;queue;constructor(e){this.controlPlane=e;this.previews=new Xe(e),this.queue=new c(e)}enqueueDeploy(e,t={}){let r=t.created?"preview.create":"preview.update",n=t.reason==="manual_rebuild"?`:${crypto.randomUUID()}`:"",o=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:t.actorId,kind:r,correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:${e.commitSha}${n}`,input:{previewId:e.id,reason:t.reason??(t.created?"create":"commit_update"),source:{repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:e.fork}},lockKey:`preview:${e.id}`,providerKey:"preview",buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:o.id}),o}enqueueDestroy(e,t,r){if(e.status==="destroyed")throw Error("Preview is already destroyed");let n=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:r,kind:"preview.destroy",correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:destroy:${t}`,input:{previewId:e.id,reason:t},lockKey:`preview:${e.id}`,providerKey:"preview",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:n.id}),n}cleanup(e={}){let t=e.now??new Date,r=new Map,n=this.previews.listInstances().filter((p)=>!["destroyed","destroying"].includes(p.status)),o=(p,E)=>{let g=r.get(p.id)??{preview:p,reasons:[]};if(!g.reasons.includes(E))g.reasons.push(E);r.set(p.id,g)};for(let p of n){if(new Date(p.expiresAt)<=t)o(p,"ttl_expired");if(e.maxAgeHours&&t.getTime()-new Date(p.createdAt).getTime()>=e.maxAgeHours*3600000)o(p,"max_age")}let a=new Map;for(let p of n)a.set(p.definitionId,[...a.get(p.definitionId)??[],p]);for(let[p,E]of a){let g=this.previews.getDefinition(p),m=e.keepCount??g?.keepCount;if(!m)continue;E.sort((T,h)=>h.createdAt.localeCompare(T.createdAt)).slice(m).forEach((T)=>o(T,"keep_count"))}let d=[...r.values()].sort((p,E)=>p.preview.createdAt.localeCompare(E.preview.createdAt)),u=e.dryRun?[]:d.map((p)=>this.enqueueDestroy(p.preview,p.reasons.sort().join("+"),e.actorId));if(d.length)this.controlPlane.appendEvent({actorId:e.actorId,type:e.dryRun?"preview.cleanup.planned":"preview.cleanup.queued",payload:{previewIds:d.map((p)=>p.preview.id),reasons:Object.fromEntries(d.map((p)=>[p.preview.id,p.reasons])),dryRun:!!e.dryRun}});return{candidates:d,operations:u,dryRun:!!e.dryRun}}reconcile(e){let t=[],r=[],n=[];for(let o of e){let a=o.tags["ts-cloud:preview"],d=o.tags["ts-cloud:project"],u=o.tags["ts-cloud:expires-at"];if(!a||!d||!u){n.push(o.providerResourceId);continue}let p=this.previews.getInstance(a);if(!p||p.projectId!==d||p.expiresAt!==u){r.push(o.providerResourceId);continue}if(this.previews.recordResource({...o,previewId:p.id}),o.estimatedMonthlyCost!==void 0)this.previews.transition(p.id,p.status,{costEstimate:o.estimatedMonthlyCost,observedState:{...p.observedState,lastReconciledAt:new Date().toISOString()}});t.push(o.providerResourceId)}if(r.length)this.controlPlane.appendEvent({type:"preview.reconciliation.leaks",level:"error",payload:{providerResourceIds:r}});return{matched:t,unknownPreviewResources:r,ignoredUntagged:n}}}var kA=["deployment.create","deployment.rollback","application.create","deploy.source","deploy.preview","preview.create","preview.update","preview.destroy","compose.deploy","compose.redeploy","compose.start","compose.stop","compose.delete","compose.scale"];function Ue(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function NA(e,t){if(!t.projectId||!t.environmentId)throw Error(`Queued ${t.kind} operation is missing its project or environment scope`);let r=e.listEnvironments(t.projectId).find((d)=>d.id===t.environmentId);if(!r)throw Error(`Environment ${t.environmentId} was not found for queued ${t.kind} operation`);let n=t.resourceId?e.getResource(t.resourceId):void 0;if(t.resourceId&&(!n||n.projectId!==t.projectId||n.environmentId!==t.environmentId))throw Error(`Resource ${t.resourceId} was not found in the queued deployment scope`);let o=Ue(t.input);if(t.kind.startsWith("compose.")){let d=typeof o.applicationId==="string"?o.applicationId:void 0,u=d?new or(e).get(d):t.resourceId?new or(e).getByResource(t.resourceId):void 0;if(!u||u.projectId!==t.projectId||u.environmentId!==t.environmentId||u.resourceId!==t.resourceId)throw Error("Queued Compose application does not match the operation scope");let p=t.kind.slice(8),E=["compose:apply",u.id,"--action",p,"--env",r.slug];if(typeof o.service==="string"&&o.service)E.push("--service",o.service);if(typeof o.replicas==="number")E.push("--replicas",String(o.replicas));if(o.removeVolumes===!0)E.push("--remove-volumes");return{id:`queue:${t.id}`,label:`${p[0].toUpperCase()}${p.slice(1)} Compose application`,description:`${p} ${u.name}.`,command:E,mutates:!0,target:{environment:r.slug,resource:n?.slug,composeId:u.id}}}if(t.kind.startsWith("preview.")){let d=typeof o.previewId==="string"?o.previewId:void 0,u=d?new Xe(e).getInstance(d):void 0;if(!u)throw Error(`Preview ${d??"(missing)"} was not found for queued ${t.kind}`);if(u.projectId!==t.projectId||u.resourceId!==t.resourceId)throw Error("Queued preview does not match the operation scope");if(t.kind==="preview.destroy")return{id:`queue:${t.id}`,label:"Destroy preview",description:`Destroy ${u.name}.`,command:["stack:delete",u.stackName,"--yes"],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:u.id}};return{id:`queue:${t.id}`,label:t.kind==="preview.create"?"Create preview":"Update preview",description:`Deploy ${u.name} at ${u.commitSha}.`,command:["deploy","--stack",u.stackName,"--env",r.slug,"--yes","--skip-dns-verification",...n?["--site",n.slug]:[]],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:u.id}}}if(t.kind==="deployment.rollback"){let d=["deploy:rollback"];if(n)d.push(n.slug);if(d.push("--env",r.slug),typeof o.revision==="string"&&o.revision)d.push("--to",o.revision);return{id:`queue:${t.id}`,label:"Rollback deployment",description:`Roll back ${n?.slug??r.slug}.`,command:d,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}let a=["deploy","--env",r.slug,"--yes"];if(n)a.push("--site",n.slug);return{id:`queue:${t.id}`,label:t.kind==="deploy.preview"?"Deploy preview":"Deploy release",description:`Deploy ${n?.slug??r.slug}.`,command:a,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}function pn(e){let t=e.stderr?.trim()||`Deployment process exited with code ${e.exitCode}`;if(/\b(?:429|rate.?limit|throttl)/i.test(t))return new ce(t,"provider_throttled");if(/\b(?:502|503|504|temporar(?:y|ily)|unavailable|provider.?error)/i.test(t))return new ce(t,"provider_unavailable");if(/\b(?:network|econn|enotfound|socket|timed?\s*out|fetch failed|dns)\b/i.test(t))return new ce(t,"network");return Error(t)}function Rd(e){let t=async(r)=>{r.checkpoint("prepare","Resolving the persisted deployment target.");let n=NA(e.store,r.operation),o=n.target.previewId?new Xe(e.store):void 0,a=n.target.composeId?new or(e.store):void 0;if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"destroying":r.operation.kind==="preview.update"?"updating":"deploying",{operationId:r.operation.id});if(a&&n.target.composeId)a.transition(n.target.composeId,r.operation.kind==="compose.delete"?"deleting":r.operation.kind==="compose.stop"?"stopped":"deploying",{operationId:r.operation.id});r.log(`Target: ${n.target.resource??"all resources"} in ${n.target.environment}.`,{stream:"system"}),r.throwIfCancellationRequested(),r.checkpoint("execute",`Running cloud ${n.command.join(" ")}.`);let d=await e.execute(n,r);if(!d.ok){if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"cleanup_failed":"failed",{operationId:r.operation.id,teardownError:r.operation.kind==="preview.destroy"?d.stderr?.trim()||`Process exited with ${d.exitCode}`:void 0});if(a&&n.target.composeId)a.transition(n.target.composeId,r.operation.kind==="compose.delete"?"degraded":"failed",{operationId:r.operation.id,error:d.stderr?.trim()||`Process exited with ${d.exitCode}`});throw pn(d)}if(r.throwIfCancellationRequested(),o&&n.target.previewId){let u=o.getInstance(n.target.previewId);if(r.operation.kind==="preview.destroy")o.markResourcesDeleted(u.id),o.transition(u.id,"destroyed",{operationId:r.operation.id,observedState:{reconciledResourceIds:o.listResources(u.id).map((p)=>p.providerResourceId),exactCommitSha:u.commitSha}});else{let p=e.store.getResource(u.resourceId)?.provider??"default";o.recordResource({previewId:u.id,provider:p,providerResourceId:u.stackName,kind:"stack",tags:{"ts-cloud:preview":u.id,"ts-cloud:project":u.projectId,"ts-cloud:expires-at":u.expiresAt},observedState:{command:d.command??null,exactCommitSha:u.commitSha}}),o.transition(u.id,"active",{operationId:r.operation.id,observedState:{url:u.url??null,stackName:u.stackName,exactCommitSha:u.commitSha,providerStatus:"deployed"}})}}if(a&&n.target.composeId){let u=a.get(n.target.composeId),p=typeof Ue(r.operation.input).service==="string"?String(Ue(r.operation.input).service):void 0,E=r.operation.kind==="compose.delete"?"deleted":r.operation.kind==="compose.stop"?"stopped":"running",g=a.transition(u.id,E,{operationId:r.operation.id,services:Object.values(u.manifest.spec.services).filter((m)=>!p||m.name===p).map((m)=>({name:m.name,status:E==="stopped"||E==="deleted"?"stopped":"running",replicas:E==="deleted"?0:m.replicas,healthyReplicas:E==="running"?m.replicas:0,observedState:{command:d.command??null,healthGatePassed:E==="running"}}))});if(E==="deleted")Jp(e.store,g,Ue(r.operation.input).removeVolumes===!0)}return r.checkpoint("finalize","Deployment command completed; persisting the terminal result."),{command:d.command??`cloud ${n.command.join(" ")}`,exitCode:d.exitCode,environment:n.target.environment,resource:n.target.resource??null}};return Object.fromEntries(kA.map((r)=>[r,t]))}var nt=/^[a-z0-9][a-z0-9_.-]{1,62}$/,En=/^0?[0-7]{3}$/,mn=["/","/boot","/dev","/etc","/proc","/root","/run","/sys","/var/run","/var/lib/docker","/var/lib/containers"],Tn=["create","attach","detach","resize","snapshot","restore","delete","adopt","usage"],gn=(e)=>e&&typeof e==="object"&&!Array.isArray(e)?e:{};function BA(e){return Object.fromEntries(Tn.map((t)=>[t,{supported:!1,reason:e}]))}function Eo(e,t={}){let r=BA("This storage driver does not support the operation.");for(let n of e)r[n]={supported:!0};return{...r,...t}}function xA(e){if(!e.startsWith("/")||e.includes("\x00")||e.split("/").includes(".."))throw Error("Mount target must be an absolute normalized path without traversal.");let t=e.replace(/\/+$/,"")||"/";if(mn.some((r)=>t===r||t.startsWith(`${r}/`)))throw Error(`Mount target ${e} is a protected host or runtime path.`)}function OA(e){if(xA(e.targetPath),e.uid!=null&&(!Number.isInteger(e.uid)||e.uid<0))throw Error("Mount UID must be a non-negative integer.");if(e.gid!=null&&(!Number.isInteger(e.gid)||e.gid<0))throw Error("Mount GID must be a non-negative integer.");if(e.mode&&!En.test(e.mode))throw Error("Mount mode must be a three or four digit octal value.");if(e.propagation&&!["private","rprivate","shared","rshared","slave","rslave"].includes(e.propagation))throw Error("Unsupported mount propagation mode.")}class vo{store;drivers;now;queue;constructor(e,t,r,n=()=>new Date){this.store=e;this.drivers=t;this.now=n;this.queue=r??new c(e.controlPlane)}driver(e,t){let r=this.drivers.find((n)=>n.provider===e&&n.type===t);if(!r)throw Error(`No ${e} ${t} volume driver is configured.`);return r}capability(e,t){let r=e.capabilities[t];if(!r?.supported)throw Error(r?.reason??`${t} is unsupported for this volume.`)}queueMutation(e,t,r,n,o){return this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:o??e.resourceId,actorId:n,kind:t,idempotencyKey:`${t}:${e.id}:v${e.version}:${JSON.stringify(r)}`,correlationId:`volume:${e.id}`,input:{volumeId:e.id,...r},lockKey:o?`resource:${o}`:`volume:${e.id}`,providerKey:e.provider,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:365}).operation}create(e){if(!nt.test(e.name))throw Error("Volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");if(e.capacityBytes!=null&&(!Number.isSafeInteger(e.capacityBytes)||e.capacityBytes<=0))throw Error("Volume capacity must be a positive byte count.");let t=this.store.controlPlane.getProject(e.projectId),r=e.environmentId?this.store.controlPlane.listEnvironments(e.projectId).find((E)=>E.id===e.environmentId):void 0,n=e.resourceId?this.store.controlPlane.getResource(e.resourceId):void 0;if(!t||t.organizationId!==e.organizationId)throw Error("Volume project does not belong to the organization.");if(e.environmentId&&!r)throw Error("Volume environment does not belong to the project.");if(n&&(n.projectId!==e.projectId||n.environmentId!==e.environmentId||n.kind!=="volume"))throw Error("Volume resource does not belong to the selected scope.");let o=n??this.store.controlPlane.createResource({projectId:e.projectId,environmentId:e.environmentId,kind:"volume",slug:e.name,name:e.name,provider:e.provider,desiredState:{type:e.type,capacityBytes:e.capacityBytes??null,filesystem:e.filesystem??null,encrypted:!!e.encrypted}}),a=this.driver(e.provider,e.type),d=a.capabilities(),u=this.store.create({organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,resourceId:o.id,name:e.name,provider:e.provider,type:e.type,status:"pending",capacityBytes:e.capacityBytes,filesystem:e.filesystem,encrypted:!!e.encrypted,capabilities:d,desiredState:e.desiredState??{},observedState:{}}),p=this.queueMutation(u,"volume.create",{},e.actorId);return this.store.audit({organizationId:u.organizationId,projectId:u.projectId,environmentId:u.environmentId,actorId:e.actorId,type:"volume.create.queued",volumeId:u.id,payload:{name:u.name,type:u.type}}),{volume:u,operation:p}}attach(e,t){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"attach"),OA(t);let n=this.store.controlPlane.getResource(t.resourceId);if(!n||n.projectId!==r.projectId||n.environmentId!==r.environmentId)throw Error("Cross-project or cross-environment volume attachments are forbidden.");let o=this.store.upsertAttachment({volumeId:e,resourceId:t.resourceId,targetPath:t.targetPath,readOnly:!!t.readOnly,uid:t.uid,gid:t.gid,mode:t.mode,propagation:t.propagation??"private",driverOptions:t.driverOptions??{},desiredState:"attached",observedState:"pending"}),a=this.queueMutation(r,"volume.attach",{attachmentId:o.id},t.actorId,t.resourceId);return this.store.updateAttachment(o.id,{operationId:a.id}),this.store.update(r.id,r.version,{status:"attaching"}),this.store.audit({organizationId:r.organizationId,projectId:r.projectId,environmentId:r.environmentId,actorId:t.actorId,type:"volume.attach.queued",volumeId:e,payload:{resourceId:t.resourceId,targetPath:t.targetPath}}),{volume:this.store.get(r.id),attachment:this.store.attachment(o.id),operation:a}}detach(e,t,r={}){let n=this.store.get(e),o=this.store.attachment(t);if(!n||!o||o.volumeId!==e)throw Error("Volume attachment was not found.");if(this.capability(n,"detach"),o.observedState==="attached"&&(!r.drained||!r.unmounted))throw Error("Detach requires completed workload drain and filesystem unmount checkpoints.");if(r.force&&r.confirmation!==`detach ${n.name}`)throw Error(`Force detach requires confirmation: detach ${n.name}`);let a=this.store.updateAttachment(t,{desiredState:"detached"}),d=this.queueMutation(n,"volume.detach",{attachmentId:t,force:!!r.force},r.actorId,o.resourceId);return this.store.updateAttachment(t,{operationId:d.id}),this.store.update(n.id,n.version,{status:"detaching"}),{volume:this.store.get(e),attachment:a,operation:d}}resize(e,t,r={}){let n=this.store.get(e);if(!n)throw Error("Volume was not found.");if(this.capability(n,"resize"),!Number.isSafeInteger(t)||t<=0)throw Error("Volume capacity must be a positive byte count.");if(n.capacityBytes!=null&&t<n.capacityBytes)throw Error("Volume shrinking is not supported because it can corrupt data.");let o=n.capabilities.resize;if(o.minimumBytes&&t<o.minimumBytes)throw Error(`Minimum supported capacity is ${o.minimumBytes} bytes.`);if(o.maximumBytes&&t>o.maximumBytes)throw Error(`Maximum supported capacity is ${o.maximumBytes} bytes.`);if(o.online===!1&&!r.drained)throw Error("This resize requires a completed workload drain checkpoint.");let a=this.store.update(e,n.version,{status:"resizing",desiredState:{...n.desiredState,capacityBytes:t}}),d=this.queueMutation(a,"volume.resize",{capacityBytes:t},r.actorId);return{volume:a,operation:d}}snapshot(e,t={}){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"snapshot");let n=this.store.createSnapshot({volumeId:e,name:t.name??`${r.name}-${this.now().toISOString().replace(/[:.]/g,"-")}`,status:"pending",encrypted:r.encrypted,metadata:{}}),o=this.store.update(e,r.version,{status:"snapshotting"}),a=this.queueMutation(o,"volume.snapshot",{snapshotId:n.id},t.actorId);return{volume:o,snapshot:n,operation:a}}restore(e,t){let r=this.store.snapshot(e),n=r?this.store.get(r.volumeId):void 0;if(!r||!n||r.status!=="available")throw Error("An available volume snapshot is required for restore.");if(this.capability(n,"restore"),!nt.test(t.name))throw Error("Restored volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");let o=this.store.controlPlane.createResource({projectId:n.projectId,environmentId:n.environmentId,kind:"volume",slug:t.name,name:t.name,provider:n.provider,desiredState:{restoreFromSnapshotId:r.id}}),a=this.store.create({organizationId:n.organizationId,projectId:n.projectId,environmentId:n.environmentId,resourceId:o.id,name:t.name,provider:n.provider,type:n.type,status:"pending",capacityBytes:r.sizeBytes??n.capacityBytes,filesystem:n.filesystem,encrypted:r.encrypted,capabilities:n.capabilities,desiredState:{restoreFromSnapshotId:r.id,sourceVolumeId:n.id},observedState:{}}),d=this.queueMutation(a,"volume.restore",{snapshotId:r.id,sourceVolumeId:n.id},t.actorId);return{volume:a,snapshot:r,operation:d}}delete(e,t){let r=this.store.get(e);if(!r)throw Error("Volume was not found.");this.capability(r,"delete");let n=this.store.attachments(e).filter((u)=>u.desiredState==="attached"||u.observedState==="attached");if(n.length)throw Error(`Detach ${n.length} active consumer(s) before deleting this volume.`);if(!t.recentAuthAt||this.now().getTime()-new Date(t.recentAuthAt).getTime()>900000)throw Error("Volume deletion requires authentication verified within the last 15 minutes.");if(t.confirmation!==r.name)throw Error(`Type ${r.name} to confirm permanent volume deletion.`);if(!(r.lastBackupAt&&this.now().getTime()-new Date(r.lastBackupAt).getTime()<=86400000)&&(!t.backupOverride||t.backupOverrideConfirmation!==`delete without backup ${r.name}`))throw Error(`A verified backup from the last 24 hours is required, or confirm: delete without backup ${r.name}`);let a=this.store.update(e,r.version,{status:"deleting"}),d=this.queueMutation(a,"volume.delete",{backupOverride:!!t.backupOverride},t.actorId);return{volume:a,operation:d}}async discover(e){let t=new Set;for(let r of this.drivers)for(let n of await r.discover(e.projectId,e.environmentId)){let o=this.store.list({projectId:e.projectId,environmentId:e.environmentId}).find((d)=>d.provider===r.provider&&d.providerId===n.providerId);if(o){t.add(o.id),this.store.update(o.id,o.version,{capacityBytes:n.capacityBytes,usedBytes:n.usedBytes,filesystem:n.filesystem,encrypted:n.encrypted??o.encrypted,observedState:n.raw??{},status:o.status==="orphaned"?"available":o.status,orphanedAt:void 0});continue}let a=this.store.create({organizationId:e.organizationId,projectId:e.projectId,environmentId:e.environmentId,name:`orphan-${n.providerId}`.toLowerCase().replace(/[^a-z0-9_.-]/g,"-").slice(0,63),provider:r.provider,providerId:n.providerId,type:r.type,status:"orphaned",capacityBytes:n.capacityBytes,usedBytes:n.usedBytes,filesystem:n.filesystem,encrypted:!!n.encrypted,capabilities:r.capabilities(),desiredState:{},observedState:n.raw??{},orphanedAt:this.now().toISOString()});t.add(a.id)}return this.store.list({projectId:e.projectId,environmentId:e.environmentId})}adopt(e,t){let r=this.store.get(e);if(!r||r.status!=="orphaned")throw Error("Only discovered orphan volumes can be adopted.");if(!nt.test(t.name))throw Error("Volume names must be 2-63 lowercase letters, numbers, dots, dashes, or underscores.");let n=this.store.update(e,r.version,{name:t.name,status:"available",adoptedAt:this.now().toISOString(),orphanedAt:void 0});return this.store.audit({organizationId:r.organizationId,projectId:r.projectId,environmentId:r.environmentId,actorId:t.actorId,type:"volume.adopted",volumeId:e,payload:{providerId:r.providerId??null}}),n}}function _n(e){let t=gn(e.input);if(typeof t.volumeId!=="string")throw Error("Queued volume operation is missing its volume identity.");return{volumeId:t.volumeId,sourceVolumeId:typeof t.sourceVolumeId==="string"?t.sourceVolumeId:void 0,attachmentId:typeof t.attachmentId==="string"?t.attachmentId:void 0,snapshotId:typeof t.snapshotId==="string"?t.snapshotId:void 0,capacityBytes:typeof t.capacityBytes==="number"?t.capacityBytes:void 0,force:t.force===!0}}function Dd(e,t){let r=(o)=>{let a=t.find((d)=>d.provider===o.provider&&d.type===o.type);if(!a)throw Error(`No ${o.provider} ${o.type} volume driver is configured.`);return a},n=async(o)=>{let a=_n(o.operation),d=e.get(a.volumeId);if(!d)throw Error("Queued volume was not found.");let u=r(d);o.checkpoint("preflight","Validating persistent volume identity and capabilities."),o.throwIfCancellationRequested();let p;if(o.operation.kind==="volume.create")p=await u.create(d),e.update(d.id,d.version,{providerId:p.providerId,capacityBytes:p.capacityBytes??d.capacityBytes,usedBytes:p.usedBytes,filesystem:p.filesystem??d.filesystem,encrypted:p.encrypted??d.encrypted,observedState:p.raw??{},status:"available"});else if(o.operation.kind==="volume.attach"){let E=a.attachmentId?e.attachment(a.attachmentId):void 0;if(!E)throw Error("Queued volume attachment was not found.");await u.attach(d,E),e.updateAttachment(E.id,{observedState:"attached",lastError:void 0}),e.update(d.id,d.version,{status:"attached"})}else if(o.operation.kind==="volume.detach"){let E=a.attachmentId?e.attachment(a.attachmentId):void 0;if(!E)throw Error("Queued volume attachment was not found.");await u.detach(d,E,{force:a.force}),e.updateAttachment(E.id,{observedState:"detached",lastError:void 0});let g=e.attachments(d.id).some((m)=>m.id!==E.id&&m.observedState==="attached");e.update(d.id,d.version,{status:g?"attached":"available"})}else if(o.operation.kind==="volume.resize"){if(!a.capacityBytes)throw Error("Queued volume resize is missing its capacity.");p=await u.resize(d,a.capacityBytes),e.update(d.id,d.version,{capacityBytes:p.capacityBytes??a.capacityBytes,usedBytes:p.usedBytes??d.usedBytes,observedState:p.raw??d.observedState,status:e.attachments(d.id).some((E)=>E.observedState==="attached")?"attached":"available"})}else if(o.operation.kind==="volume.snapshot"){let E=a.snapshotId?e.snapshot(a.snapshotId):void 0;if(!E)throw Error("Queued volume snapshot was not found.");let g=await u.snapshot(d,E);e.updateSnapshot(E.id,{...g,status:"available"}),e.update(d.id,d.version,{status:e.attachments(d.id).some((m)=>m.observedState==="attached")?"attached":"available",lastBackupAt:new Date().toISOString()})}else if(o.operation.kind==="volume.restore"){let E=a.snapshotId?e.snapshot(a.snapshotId):void 0,g=a.sourceVolumeId?e.get(a.sourceVolumeId):void 0;if(!E||!g)throw Error("Queued volume restore source was not found.");p=await u.restore(g,E,d),e.update(d.id,d.version,{providerId:p.providerId,capacityBytes:p.capacityBytes??d.capacityBytes,usedBytes:p.usedBytes,filesystem:p.filesystem??d.filesystem,encrypted:p.encrypted??d.encrypted,observedState:p.raw??{},status:"available"})}else if(o.operation.kind==="volume.delete")await u.delete(d),e.update(d.id,d.version,{status:"deleted",deletedAt:new Date().toISOString()});return o.checkpoint("finalize","Persisted observed volume state."),{volumeId:d.id,status:e.get(d.id)?.status??"deleted"}};return Object.fromEntries(["volume.create","volume.attach","volume.detach","volume.resize","volume.snapshot","volume.restore","volume.delete"].map((o)=>[o,n]))}var vn=async(e)=>{let t=Bun.spawn(["docker",...e],{stdout:"pipe",stderr:"pipe"}),[r,n,o]=await Promise.all([t.exited,new Response(t.stdout).text(),new Response(t.stderr).text()]);return{code:r,stdout:n,stderr:o}},Z=/^[A-Za-z0-9][A-Za-z0-9_.-]{1,127}$/;class Yr{command;provider="docker";type="docker";constructor(e=vn){this.command=e}capabilities(){return Eo(["create","attach","detach","delete","adopt","usage"],{resize:{supported:!1,reason:"Docker named volumes do not expose a portable capacity resize operation."},snapshot:{supported:!1,reason:"Attach a volume backup policy to create verified recovery points."},restore:{supported:!1,reason:"Restore this volume from its verified backup recovery point."}})}async run(e,t=!1){let r=await this.command(e);if(r.code!==0&&!t)throw Error(`Docker volume command failed: ${r.stderr.trim()||r.code}`);return r.stdout}async inspect(e){let t=await this.run(["volume","inspect",e],!0);if(!t.trim())return;let r;try{r=JSON.parse(t)[0]}catch{return}return{providerId:String(r.Name??e),raw:{driver:String(r.Driver??"local"),mountpoint:String(r.Mountpoint??""),labels:r.Labels??{}}}}async discover(e,t){let r=await this.run(["volume","ls","--format","{{.Name}}"]),n=[];for(let o of r.split(`
1566
1566
  `).map((a)=>a.trim()).filter(Z.test.bind(Z))){let a=await this.inspect(o);if(a)n.push(a)}return n}async create(e){let t=typeof e.desiredState.nativeName==="string"?e.desiredState.nativeName:e.name;if(!Z.test(t))throw Error("Docker volume name is invalid.");return await this.run(["volume","create","--label",`ts-cloud.volume=${e.id}`,"--label",`ts-cloud.project=${e.projectId}`,t]),await this.inspect(t)??{providerId:t}}async attach(e,t){}async detach(e,t){}async resize(){throw Error(this.capabilities().resize.reason)}async snapshot(){throw Error(this.capabilities().snapshot.reason)}async restore(e,t,r){throw Error(this.capabilities().restore.reason)}async delete(e){if(!e.providerId||!Z.test(e.providerId))throw Error("Docker volume provider identity is missing or invalid.");await this.run(["volume","rm",e.providerId])}async usage(e){let t=await this.run(["system","df","-v","--format","{{json .}}"],!0),r=t.split(`
1567
1567
  `).find((n)=>n.includes(`"Name":"${e.providerId}"`));if(!r)return{};try{let n=JSON.parse(r);return{usedBytes:typeof n.Size==="number"?n.Size:void 0}}catch{return{}}}}class To{provider="server";type="server_path";root;constructor(e){this.root=jt(e)}capabilities(){return Eo(["create","attach","detach","delete","adopt","usage"],{resize:{supported:!1,reason:"Server paths use the capacity of their containing filesystem."},snapshot:{supported:!1,reason:"Attach a filesystem backup policy for verified recovery points."},restore:{supported:!1,reason:"Restore a filesystem recovery point into a new managed path."}})}path(e){if(!Z.test(e))throw Error("Server path volume name is invalid.");let t=jt(this.root,e);if(!t.startsWith(`${this.root}${Ln}`)||yn(t)!==e)throw Error("Server path escaped the managed volume root.");return t}async discover(e,t){return await it(this.root,{recursive:!0,mode:488}),(await hn(this.root,{withFileTypes:!0})).filter((n)=>n.isDirectory()&&Z.test(n.name)).map((n)=>({providerId:n.name,raw:{path:this.path(n.name)}}))}async create(e){let t=typeof e.desiredState.nativeName==="string"?e.desiredState.nativeName:e.name,r=this.path(t);return await it(this.root,{recursive:!0,mode:488}),await it(r,{recursive:!1,mode:488}),{providerId:t,filesystem:"host",raw:{path:r}}}async attach(e,t){}async detach(e,t){}async resize(){throw Error(this.capabilities().resize.reason)}async snapshot(){throw Error(this.capabilities().snapshot.reason)}async restore(e,t,r){throw Error(this.capabilities().restore.reason)}async delete(e){if(!e.providerId)throw Error("Server path provider identity is unavailable.");await Nn(this.path(e.providerId),{recursive:!0,force:!1})}async usage(e){if(!e.providerId)return{};return{usedBytes:(await fn(this.path(e.providerId))).size}}}class _A{provider;transport;type="ebs";constructor(e,t){this.provider=e;this.transport=t}capabilities(){return Eo(["create","attach","detach","resize","snapshot","restore","delete","adopt","usage"],{resize:{supported:!0,online:!0,minimumBytes:1073741824}})}discover(e,t){return this.transport.list(e,t)}create(e){return this.transport.create({name:e.name,projectId:e.projectId,environmentId:e.environmentId,capacityBytes:e.capacityBytes,encrypted:e.encrypted,filesystem:e.filesystem})}resource(e,t){let r=e.resourceId===t.resourceId?e.observedState.resourceProviderId:void 0,n=typeof r==="string"?r:t.driverOptions.resourceProviderId;if(typeof n!=="string"||!n)throw Error("Cloud attachment requires a reviewed resourceProviderId driver option.");return n}attach(e,t){return this.transport.attach(e.providerId,this.resource(e,t),t.targetPath,t.readOnly)}detach(e,t,r){return this.transport.detach(e.providerId,this.resource(e,t),r.force)}resize(e,t){return this.transport.resize(e.providerId,t)}snapshot(e,t){return this.transport.snapshot(e.providerId,t.name)}restore(e,t,r){if(!t.providerId)throw Error("Cloud snapshot provider identity is unavailable.");return this.transport.restore(e.providerId,t.providerId,r.name)}delete(e){return this.transport.delete(e.providerId)}usage(e){return this.transport.usage(e.providerId)}}var P=(e)=>e==null?void 0:String(e),le=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},st=(e)=>Number(e)===1,ee=(e)=>e().toISOString();function Ft(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:P(e.environment_id),resourceId:P(e.resource_id),name:String(e.name),provider:String(e.provider),providerId:P(e.provider_id),type:String(e.type),status:String(e.status),capacityBytes:e.capacity_bytes==null?void 0:Number(e.capacity_bytes),usedBytes:e.used_bytes==null?void 0:Number(e.used_bytes),filesystem:P(e.filesystem),encrypted:st(e.encrypted),capabilities:le(e.capabilities,{}),desiredState:le(e.desired_state,{}),observedState:le(e.observed_state,{}),backupPolicyId:P(e.backup_policy_id),lastBackupAt:P(e.last_backup_at),orphanedAt:P(e.orphaned_at),adoptedAt:P(e.adopted_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:P(e.deleted_at)}}function ot(e){return{id:String(e.id),volumeId:String(e.volume_id),resourceId:String(e.resource_id),targetPath:String(e.target_path),readOnly:st(e.read_only),uid:e.uid==null?void 0:Number(e.uid),gid:e.gid==null?void 0:Number(e.gid),mode:P(e.mode),propagation:String(e.propagation),driverOptions:le(e.driver_options,{}),desiredState:String(e.desired_state),observedState:String(e.observed_state),operationId:P(e.operation_id),lastError:P(e.last_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Mt(e){return{id:String(e.id),volumeId:String(e.volume_id),recoveryPointId:P(e.recovery_point_id),providerId:P(e.provider_id),name:String(e.name),status:String(e.status),sizeBytes:e.size_bytes==null?void 0:Number(e.size_bytes),encrypted:st(e.encrypted),checksum:P(e.checksum),metadata:le(e.metadata,{}),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:P(e.deleted_at)}}class sr{controlPlane;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.controlPlane=e;this.now=t;this.id=r}get(e){let t=this.controlPlane.database.query("SELECT * FROM persistent_volumes WHERE id=?").get(e);return t?Ft(t):void 0}list(e){let t=["project_id=?"],r=[e.projectId];if(e.environmentId)t.push("environment_id=?"),r.push(e.environmentId);if(!e.includeDeleted)t.push("deleted_at IS NULL");return this.controlPlane.database.query(`SELECT * FROM persistent_volumes WHERE ${t.join(" AND ")} ORDER BY name`).all(...r).map(Ft)}create(e){let t=ee(this.now),r=e.id??this.id();return this.controlPlane.database.run("INSERT INTO persistent_volumes (id,organization_id,project_id,environment_id,resource_id,name,provider,provider_id,type,status,capacity_bytes,used_bytes,filesystem,encrypted,capabilities,desired_state,observed_state,backup_policy_id,last_backup_at,orphaned_at,adopted_at,created_at,updated_at,deleted_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[r,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.name,e.provider,e.providerId??null,e.type,e.status,e.capacityBytes??null,e.usedBytes??null,e.filesystem??null,e.encrypted?1:0,JSON.stringify(e.capabilities),JSON.stringify(e.desiredState),JSON.stringify(e.observedState),e.backupPolicyId??null,e.lastBackupAt??null,e.orphanedAt??null,e.adoptedAt??null,t,t,e.deletedAt??null]),this.get(r)}update(e,t,r){let n=this.get(e);if(!n||n.version!==t)throw Error("Volume changed before this operation could be applied.");let o={...n,...r,updatedAt:ee(this.now)};if(this.controlPlane.database.run("UPDATE persistent_volumes SET environment_id=?,resource_id=?,name=?,provider=?,provider_id=?,type=?,status=?,capacity_bytes=?,used_bytes=?,filesystem=?,encrypted=?,capabilities=?,desired_state=?,observed_state=?,backup_policy_id=?,last_backup_at=?,orphaned_at=?,adopted_at=?,deleted_at=?,version=version+1,updated_at=? WHERE id=? AND version=?",[o.environmentId??null,o.resourceId??null,o.name,o.provider,o.providerId??null,o.type,o.status,o.capacityBytes??null,o.usedBytes??null,o.filesystem??null,o.encrypted?1:0,JSON.stringify(o.capabilities),JSON.stringify(o.desiredState),JSON.stringify(o.observedState),o.backupPolicyId??null,o.lastBackupAt??null,o.orphanedAt??null,o.adoptedAt??null,o.deletedAt??null,o.updatedAt,e,t]).changes!==1)throw Error("Volume changed before this operation could be applied.");return this.get(e)}attachments(e){return this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE volume_id=? ORDER BY target_path").all(e).map(ot)}attachment(e){let t=this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE id=?").get(e);return t?ot(t):void 0}upsertAttachment(e){let t=this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE volume_id=? AND resource_id=? AND target_path=?").get(e.volumeId,e.resourceId,e.targetPath),r=ee(this.now);if(t){let o=ot(t);return this.controlPlane.database.run("UPDATE volume_attachments SET read_only=?,uid=?,gid=?,mode=?,propagation=?,driver_options=?,desired_state=?,observed_state=?,operation_id=?,last_error=?,version=version+1,updated_at=? WHERE id=?",[e.readOnly?1:0,e.uid??null,e.gid??null,e.mode??null,e.propagation,JSON.stringify(e.driverOptions),e.desiredState,e.observedState,e.operationId??null,e.lastError??null,r,o.id]),this.attachment(o.id)}let n=e.id??this.id();return this.controlPlane.database.run("INSERT INTO volume_attachments (id,volume_id,resource_id,target_path,read_only,uid,gid,mode,propagation,driver_options,desired_state,observed_state,operation_id,last_error,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[n,e.volumeId,e.resourceId,e.targetPath,e.readOnly?1:0,e.uid??null,e.gid??null,e.mode??null,e.propagation,JSON.stringify(e.driverOptions),e.desiredState,e.observedState,e.operationId??null,e.lastError??null,r,r]),this.attachment(n)}updateAttachment(e,t){let r=this.attachment(e);if(!r)throw Error("Volume attachment was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE volume_attachments SET desired_state=?,observed_state=?,operation_id=?,last_error=?,version=version+1,updated_at=? WHERE id=?",[n.desiredState,n.observedState,n.operationId??null,n.lastError??null,ee(this.now),e]),this.attachment(e)}snapshots(e){return this.controlPlane.database.query("SELECT * FROM volume_snapshots WHERE volume_id=? AND deleted_at IS NULL ORDER BY created_at DESC").all(e).map(Mt)}snapshot(e){let t=this.controlPlane.database.query("SELECT * FROM volume_snapshots WHERE id=?").get(e);return t?Mt(t):void 0}createSnapshot(e){let t=e.id??this.id(),r=ee(this.now);return this.controlPlane.database.run("INSERT INTO volume_snapshots (id,volume_id,recovery_point_id,provider_id,name,status,size_bytes,encrypted,checksum,metadata,created_at,updated_at,deleted_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.volumeId,e.recoveryPointId??null,e.providerId??null,e.name,e.status,e.sizeBytes??null,e.encrypted?1:0,e.checksum??null,JSON.stringify(e.metadata),r,r,e.deletedAt??null]),this.snapshot(t)}updateSnapshot(e,t){let r=this.snapshot(e);if(!r)throw Error("Volume snapshot was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE volume_snapshots SET recovery_point_id=?,provider_id=?,name=?,status=?,size_bytes=?,encrypted=?,checksum=?,metadata=?,deleted_at=?,updated_at=? WHERE id=?",[n.recoveryPointId??null,n.providerId??null,n.name,n.status,n.sizeBytes??null,n.encrypted?1:0,n.checksum??null,JSON.stringify(n.metadata),n.deletedAt??null,ee(this.now),e]),this.snapshot(e)}inventory(e,t){return this.list({projectId:e,environmentId:t}).map((r)=>{let n=this.attachments(r.id),o=this.snapshots(r.id),a=r.lastBackupAt?Date.now()-new Date(r.lastBackupAt).getTime():1/0;return{...r,attachments:n,snapshots:o,orphaned:r.status==="orphaned",usagePercent:r.capacityBytes&&r.usedBytes!=null?Math.round(r.usedBytes/r.capacityBytes*1000)/10:void 0,backupState:r.backupPolicyId?a<=86400000?"protected":"stale":"unprotected"}})}audit(e){this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,resourceId:this.get(e.volumeId)?.resourceId,actorId:e.actorId,type:e.type,level:"warning",payload:{volumeId:e.volumeId,environmentId:e.environmentId??null,...e.payload}})}}function Pd(e,t){let r=e.getProject(t.projectId);if(!r?.organizationId)return;let n=new sr(e),o=new Yr,a=new Set(t.manifest.spec.volumes),d=new Set;for(let u of a){let p=`${t.slug}-${u}`.toLowerCase().replace(/[^a-z0-9_.-]/g,"-").slice(0,63),E=n.list({projectId:t.projectId,environmentId:t.environmentId,includeDeleted:!0}).find((h)=>h.name===p);if(E?.deletedAt)throw Error(`Compose volume ${p} was permanently deleted; rename it before redeploying.`);let g=E?.resourceId?e.getResource(E.resourceId):e.createResource({projectId:t.projectId,environmentId:t.environmentId,kind:"volume",slug:p,name:p,provider:"docker",providerId:p,desiredState:{composeApplicationId:t.id,composeVolume:u}}),m=E??n.create({organizationId:r.organizationId,projectId:t.projectId,environmentId:t.environmentId,resourceId:g?.id,name:p,provider:"docker",providerId:p,type:"docker",status:"available",encrypted:!1,capabilities:o.capabilities(),desiredState:{composeApplicationId:t.id,composeVolume:u,nativeName:p},observedState:{}});d.add(m.id);let T=new Map;for(let h of Object.values(t.manifest.spec.services))for(let _ of h.volumes.filter((N)=>N.source===u)){let N=T.get(_.target)??[];N.push(h.name),T.set(_.target,N),n.upsertAttachment({volumeId:m.id,resourceId:t.resourceId,targetPath:_.target,readOnly:_.readOnly,propagation:"private",driverOptions:{composeServices:N},desiredState:"attached",observedState:"pending"})}}for(let u of n.list({projectId:t.projectId,environmentId:t.environmentId}).filter((p)=>p.desiredState.composeApplicationId===t.id&&!d.has(p.id)))for(let p of n.attachments(u.id))n.updateAttachment(p.id,{desiredState:"detached"})}function Jp(e,t,r){let n=new sr(e);for(let o of n.list({projectId:t.projectId,environmentId:t.environmentId}).filter((a)=>a.desiredState.composeApplicationId===t.id)){for(let a of n.attachments(o.id))n.updateAttachment(a.id,{desiredState:"detached",observedState:"detached"});n.update(o.id,o.version,{status:r?"deleted":"available",deletedAt:r?new Date().toISOString():void 0})}}function te(e){return typeof e==="string"&&e?e:void 0}function at(e,t){try{return JSON.parse(String(e))}catch{return t}}function De(e){return{id:String(e.id),resourceId:String(e.resource_id),projectId:String(e.project_id),environmentId:String(e.environment_id),name:String(e.name),slug:String(e.slug),status:String(e.status),sourceKind:String(e.source_kind),sourceHash:String(e.source_hash),redactedSource:String(e.redacted_source),manifest:at(e.manifest,{}),diagnostics:at(e.diagnostics,[]),templateId:te(e.template_id),templateVersion:te(e.template_version),latestOperationId:te(e.latest_operation_id),createdByActorId:te(e.created_by_actor_id),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:te(e.deleted_at)}}function In(e){return{applicationId:String(e.application_id),serviceName:String(e.service_name),status:String(e.status),replicas:Number(e.replicas),healthyReplicas:Number(e.healthy_replicas),latestOperationId:te(e.latest_operation_id),observedState:at(e.observed_state,{}),updatedAt:String(e.updated_at)}}class or{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}persist(e,t){if(!e.valid)throw Error(`Compose definition contains ${e.diagnostics.filter((_)=>_.severity==="error").length} blocking diagnostic(s)`);let{projectId:r,environmentId:n,name:o,slug:a}=e.manifest.metadata;if(!this.controlPlane.listEnvironments(r).find((_)=>_.id===n))throw Error("Compose project and environment scope was not found");let u=this.getBySlug(r,n,a),p=this.now().toISOString(),E=JSON.stringify(e.manifest),g=JSON.stringify(s(e.diagnostics));if(u){if(u.status==="deleted")throw Error("A deleted Compose application cannot be overwritten; choose another slug");let _=this.controlPlane.getResource(u.resourceId);if(!_)throw Error("Compose application resource was not found");this.controlPlane.updateResource(_.id,_.version,{name:o,provider:_.provider,providerId:_.providerId,desiredState:e.manifest,discoveredState:_.discoveredState,metadata:{sourceKind:t.sourceKind,templateId:t.templateId??null,templateVersion:t.templateVersion??null,sourceHash:e.sourceHash}}),this.controlPlane.database.run("UPDATE compose_applications SET name=?, status='ready', source_kind=?, source_hash=?, redacted_source=?, manifest=?, diagnostics=?, template_id=?, template_version=?, version=version+1, updated_at=? WHERE id=?",[o,t.sourceKind,e.sourceHash,e.redactedSource,E,g,t.templateId??null,t.templateVersion??null,p,u.id]);let N=Object.keys(e.manifest.spec.services);if(N.length)this.controlPlane.database.run(`DELETE FROM compose_service_states WHERE application_id=? AND service_name NOT IN (${N.map(()=>"?").join(",")})`,[u.id,...N]);for(let L of Object.values(e.manifest.spec.services))this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, observed_state, updated_at) VALUES (?, ?, 'pending', ?, 0, '{}', ?) ON CONFLICT(application_id, service_name) DO UPDATE SET replicas=excluded.replicas, updated_at=excluded.updated_at",[u.id,L.name,L.replicas,p]);this.controlPlane.appendEvent({projectId:r,resourceId:u.resourceId,actorId:t.createdByActorId,type:"compose.application.updated",payload:{applicationId:u.id,sourceHash:e.sourceHash,diagnosticCount:e.diagnostics.length,templateId:t.templateId??null,templateVersion:t.templateVersion??null}});let y=this.get(u.id);return Pd(this.controlPlane,y),y}let m=this.controlPlane.createResource({projectId:r,environmentId:n,kind:"compose_application",slug:a,name:o,desiredState:e.manifest,metadata:{sourceKind:t.sourceKind,templateId:t.templateId??null,templateVersion:t.templateVersion??null,sourceHash:e.sourceHash}}),T=this.id();this.controlPlane.database.run("INSERT INTO compose_applications (id, resource_id, project_id, environment_id, name, slug, status, source_kind, source_hash, redacted_source, manifest, diagnostics, template_id, template_version, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'ready', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[T,m.id,r,n,o,a,t.sourceKind,e.sourceHash,e.redactedSource,E,g,t.templateId??null,t.templateVersion??null,t.createdByActorId??null,p,p]);for(let _ of Object.values(e.manifest.spec.services))this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, observed_state, updated_at) VALUES (?, ?, 'pending', ?, 0, '{}', ?)",[T,_.name,_.replicas,p]);this.controlPlane.appendEvent({projectId:r,resourceId:m.id,actorId:t.createdByActorId,type:"compose.application.created",payload:{applicationId:T,sourceHash:e.sourceHash,serviceNames:Object.keys(e.manifest.spec.services),templateId:t.templateId??null}});let h=this.get(T);return Pd(this.controlPlane,h),h}import(e,t){let r=Wr(e,t);return{application:this.persist(r,{sourceKind:"compose",createdByActorId:t.createdByActorId}),parsed:r}}fromTemplate(e,t,r){let n=vd(e,t,r,r.version);return{application:this.persist(n,{sourceKind:"template",templateId:e,templateVersion:r.version??"1.0.0",createdByActorId:r.createdByActorId}),parsed:n}}preview(e,t){return Wr(e,t)}get(e){let t=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE id=?").get(e);return t?De(t):void 0}getByResource(e){let t=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE resource_id=?").get(e);return t?De(t):void 0}getBySlug(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE project_id=? AND environment_id=? AND slug=?").get(e,t,r);return n?De(n):void 0}list(e={}){return this.controlPlane.database.query("SELECT * FROM compose_applications ORDER BY updated_at DESC").all().map(De).filter((t)=>(!e.projectId||t.projectId===e.projectId)&&(!e.environmentId||t.environmentId===e.environmentId)&&(e.includeDeleted||t.status!=="deleted"))}services(e){return this.controlPlane.database.query("SELECT * FROM compose_service_states WHERE application_id=? ORDER BY service_name").all(e).map(In)}transition(e,t,r={}){let n=this.get(e);if(!n)throw Error(`Compose application ${e} was not found`);let o=this.now().toISOString(),a=t==="deleted"?o:null;this.controlPlane.database.run("UPDATE compose_applications SET status=?, latest_operation_id=COALESCE(?, latest_operation_id), version=version+1, updated_at=?, deleted_at=? WHERE id=?",[t,r.operationId??null,o,a,e]);for(let d of r.services??[])if(n.manifest.spec.services[d.name])this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, latest_operation_id, observed_state, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(application_id, service_name) DO UPDATE SET status=excluded.status, replicas=excluded.replicas, healthy_replicas=excluded.healthy_replicas, latest_operation_id=excluded.latest_operation_id, observed_state=excluded.observed_state, updated_at=excluded.updated_at",[e,d.name,d.status,d.replicas??n.manifest.spec.services[d.name].replicas,d.healthyReplicas??0,r.operationId??null,JSON.stringify(s(d.observedState??{})),o]);return this.controlPlane.appendEvent({projectId:n.projectId,resourceId:n.resourceId,operationId:r.operationId,type:`compose.application.${t}`,level:t==="failed"||t==="degraded"?"error":"info",payload:{applicationId:e,error:r.error??null}}),this.get(e)}}class Zr{controlPlane;applications;queue;constructor(e){this.controlPlane=e;this.applications=new or(e),this.queue=new c(e)}enqueue(e,t,r={}){if(e.status==="deleted")throw Error("Deleted Compose applications cannot be operated");if(r.service&&!e.manifest.spec.services[r.service])throw Error(`Compose service ${r.service} was not found`);if(t==="delete"){let o=r.removeVolumes?`${e.slug} delete volumes`:e.slug;if(r.confirmation!==o)throw Error(`Type ${o} to confirm ${r.removeVolumes?"persistent data removal":"stack deletion"}`)}if(t==="scale"&&(!r.service||!Number.isInteger(r.replicas)||r.replicas<0||r.replicas>100))throw Error("Scale requires a service and 0-100 replicas");let n=this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:r.actorId,kind:`compose.${t}`,idempotencyKey:`compose:${e.id}:${t}:${r.service??"stack"}:${r.replicas??""}:${e.version}`,correlationId:`compose:${e.id}`,input:{applicationId:e.id,service:r.service??null,replicas:r.replicas??null,removeVolumes:!!r.removeVolumes},lockKey:`compose:${e.id}`,providerKey:this.controlPlane.getResource(e.resourceId)?.provider??"default",buildSlot:t==="deploy"||t==="redeploy",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.applications.transition(e.id,t==="delete"?"deleting":t==="stop"?"stopped":t==="start"?"deploying":t==="scale"?e.status:"deploying",{operationId:n.id}),n}}var LA=["edge.requests","edge.egress_gb","function.invocations","function.gb_seconds","build.minutes","compute.instance_hours","storage.gb_hours","object.egress_gb","object.requests","database.gb_hours","database.io_requests","telemetry.ingest_gb","image.transformations"],wo={"edge.requests":{key:"edge.requests",unit:"requests",label:"Edge requests",precision:0},"edge.egress_gb":{key:"edge.egress_gb",unit:"gb",label:"Edge egress",precision:3},"function.invocations":{key:"function.invocations",unit:"invocations",label:"Function invocations",precision:0},"function.gb_seconds":{key:"function.gb_seconds",unit:"gb_seconds",label:"Function compute",precision:2},"build.minutes":{key:"build.minutes",unit:"minutes",label:"Build minutes",precision:2},"compute.instance_hours":{key:"compute.instance_hours",unit:"hours",label:"Instance hours",precision:2},"storage.gb_hours":{key:"storage.gb_hours",unit:"gb_hours",label:"Block storage",precision:2},"object.egress_gb":{key:"object.egress_gb",unit:"gb",label:"Object storage egress",precision:3},"object.requests":{key:"object.requests",unit:"requests",label:"Object storage requests",precision:0},"database.gb_hours":{key:"database.gb_hours",unit:"gb_hours",label:"Database storage",precision:2},"database.io_requests":{key:"database.io_requests",unit:"requests",label:"Database I/O",precision:0},"telemetry.ingest_gb":{key:"telemetry.ingest_gb",unit:"gb",label:"Telemetry ingest",precision:3},"image.transformations":{key:"image.transformations",unit:"count",label:"Image transformations",precision:0}},$A=["notify","block_builds","block_deployments","throttle_requests","suspend_functions","serve_static","suspend_project"],O={notify:0,block_builds:1,block_deployments:2,throttle_requests:3,suspend_functions:4,serve_static:5,suspend_project:6};var MA=1e6;function Sn(e){if(e.tiers&&e.tiers.length>0)return e.tiers;return[{upToQuantity:null,microCentsPerUnit:e.microCentsPerUnit??0}]}function kd(e,t){if(!(e>0))return 0;let r=[...t].sort((d,u)=>{if(d.upToQuantity===null)return 1;if(u.upToQuantity===null)return-1;return d.upToQuantity-u.upToQuantity}),n=e,o=0,a=0;for(let d of r){if(n<=0)break;let p=(d.upToQuantity===null?1/0:d.upToQuantity)-o;if(p<=0)continue;let E=Math.min(n,p);a+=E*d.microCentsPerUnit,n-=E,o+=E}if(n>0){let d=r.reduce((u,p)=>Math.max(u,p.microCentsPerUnit),0);a+=n*d}return a}function Xp(e,t,r,n){let o=e.entries.filter((u)=>u.meter===t);if(o.length===0)return;let a=o.filter((u)=>u.provider===r),d=a.length>0?a:o.filter((u)=>u.provider==="*");return d.find((u)=>u.region===n)??d.find((u)=>u.region==null)}function Ro(e,t,r=0){let n=Xp(e,t.meter,t.provider,t.region),o=Math.max(0,t.quantity);if(!n)return{meter:t.meter,provider:t.provider??"unknown",region:t.region,quantity:o,includedQuantity:0,billableQuantity:o,costCents:0,unpriced:!0};let a=Math.max(0,n.includedQuantity??0),d=Math.max(0,r-a),u=Math.max(0,a-Math.max(0,r)),p=Math.min(o,u),E=o-p,g=Sn(n),m=kd(d+E,g)-kd(d,g);return{meter:t.meter,provider:n.provider,region:n.region??t.region,quantity:o,includedQuantity:p,billableQuantity:E,costCents:m/1e6,unpriced:!1}}function FA(e,t){let r=new Map,n=[];for(let o of t){let a=`${o.meter}\x00${o.provider??""}\x00${o.region??""}`,d=r.get(a)??0,u=Ro(e,o,d);r.set(a,d+u.quantity),n.push(u)}return{currency:e.currency,totalCents:n.reduce((o,a)=>o+a.costCents,0),lines:n,unpricedMeters:[...new Set(n.filter((o)=>o.unpriced).map((o)=>String(o.meter)))]}}function UA(e){return Math.round(e*100)/100}function QA(e,...t){let r=new Map,n=(a)=>`${a.meter}\x00${a.provider}\x00${a.region??""}`;for(let a of e.entries)r.set(n(a),a);let o=e.currency;for(let a of t){o=a.currency||o;for(let d of a.entries)r.set(n(d),d)}return{currency:o,entries:[...r.values()]}}var G=(e)=>Math.round(e*1e6),z=(e)=>Math.round(e*1e6),Nd={currency:"USD",entries:[{meter:"edge.requests",provider:"aws",microCentsPerUnit:z(0.00075)},{meter:"edge.egress_gb",provider:"aws",includedQuantity:100,tiers:[{upToQuantity:10240,microCentsPerUnit:G(8.5)},{upToQuantity:51200,microCentsPerUnit:G(8)},{upToQuantity:null,microCentsPerUnit:G(6)}]},{meter:"function.invocations",provider:"aws",includedQuantity:1e6,microCentsPerUnit:z(0.002)},{meter:"function.gb_seconds",provider:"aws",includedQuantity:400000,microCentsPerUnit:z(0.00166667)},{meter:"storage.gb_hours",provider:"aws",microCentsPerUnit:z(0.010958904109589041)},{meter:"object.egress_gb",provider:"aws",includedQuantity:100,microCentsPerUnit:G(9)},{meter:"object.requests",provider:"aws",microCentsPerUnit:z(0.000039999999999999996)},{meter:"database.gb_hours",provider:"aws",microCentsPerUnit:z(0.015753424657534248)},{meter:"compute.instance_hours",provider:"aws",microCentsPerUnit:z(4.16)},{meter:"edge.egress_gb",provider:"hetzner",includedQuantity:20480,microCentsPerUnit:G(0.108)},{meter:"object.egress_gb",provider:"hetzner",includedQuantity:1024,microCentsPerUnit:G(0.108)},{meter:"compute.instance_hours",provider:"hetzner",microCentsPerUnit:z(0.95)},{meter:"storage.gb_hours",provider:"hetzner",microCentsPerUnit:z(0.006027397260273972)},{meter:"edge.requests",provider:"hetzner",microCentsPerUnit:0},{meter:"edge.requests",provider:"local",microCentsPerUnit:0},{meter:"edge.egress_gb",provider:"local",microCentsPerUnit:0},{meter:"function.invocations",provider:"local",microCentsPerUnit:0},{meter:"function.gb_seconds",provider:"local",microCentsPerUnit:0},{meter:"build.minutes",provider:"*",includedQuantity:6000,microCentsPerUnit:z(0.8)},{meter:"telemetry.ingest_gb",provider:"*",includedQuantity:5,microCentsPerUnit:G(50)},{meter:"image.transformations",provider:"*",includedQuantity:5000,microCentsPerUnit:z(0.05)}]};var zt=new Map;function qt(e){let t=zt.get(e);if(!t)t=new Intl.DateTimeFormat("en-US",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",weekday:"short",hourCycle:"h23"}),zt.set(e,t);return t}var bn={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};function Mi(e){try{return qt(e),!0}catch{return!1}}function Do(e,t){let r=qt(t).formatToParts(e),n=(o)=>r.find((a)=>a.type===o)?.value??"0";return{year:Number(n("year")),month:Number(n("month")),day:Number(n("day")),hour:Number(n("hour")),minute:Number(n("minute")),second:Number(n("second")),weekday:bn[n("weekday")]??0}}function Bd(e,t){let r=Do(e,t);return Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second)-Math.floor(e.getTime()/1000)*1000}function ar(e,t,r,n,o=0){let a=Date.UTC(t,r-1,n,o),d=new Date(a-Bd(new Date(a),e));return new Date(a-Bd(d,e))}function Rn(e,t){return new Date(Date.UTC(e,t-1,1)).toLocaleString("en-US",{month:"long",year:"numeric",timeZone:"UTC"})}function Rt(e,t,r=new Date){let n=Mi(t)?t:"UTC",o=Do(r,n),a,d,u;if(e==="daily")a=ar(n,o.year,o.month,o.day),d=ar(n,o.year,o.month,o.day+1),u=`${o.year}-${String(o.month).padStart(2,"0")}-${String(o.day).padStart(2,"0")}`;else if(e==="weekly"){let g=(o.weekday+6)%7;a=ar(n,o.year,o.month,o.day-g),d=ar(n,o.year,o.month,o.day-g+7);let m=Do(a,n);u=`week of ${m.year}-${String(m.month).padStart(2,"0")}-${String(m.day).padStart(2,"0")}`}else a=ar(n,o.year,o.month,1),d=ar(n,o.year,o.month+1,1),u=Rn(o.year,o.month);let p=d.getTime()-a.getTime(),E=Math.max(0,Math.min(p,r.getTime()-a.getTime()));return{start:a.toISOString(),end:d.toISOString(),elapsedMs:E,totalMs:p,label:u}}function HA(e,t,r=new Date){let n=Rt(e,t,r),o=new Date(new Date(n.start).getTime()-1),a=Rt(e,t,o);return{...a,elapsedMs:a.totalMs}}function en(e){let r=(typeof e==="string"?new Date(e):e).getTime();if(!Number.isFinite(r))throw Error("hourBucket requires a valid date");return new Date(Math.floor(r/3600000)*3600000).toISOString()}function GA(e,t,r=9600){let n=Math.floor(new Date(e).getTime()/3600000)*3600000,o=new Date(t).getTime();if(!Number.isFinite(n)||!Number.isFinite(o))throw Error("hourBucketsBetween requires valid dates");let a=[];for(let d=n;d<o&&a.length<r;d+=3600000)a.push(new Date(d).toISOString());return a}import{createHash as Cn}from"node:crypto";var we=1073741824,xd=[{match:"request.count",meter:"edge.requests"},{match:"traffic.requests",meter:"edge.requests"},{match:"http.request",meter:"edge.requests",field:"count"},{match:"traffic.bytes_out",meter:"edge.egress_gb",scale:1/we},{match:"storage.egress.day",meter:"object.egress_gb",scale:1/we},{match:"storage.egress.month",meter:"object.egress_gb",scale:1/we,cumulative:!0},{match:"storage.egress.day_downloads",meter:"object.requests"},{match:"function.invocation",meter:"function.invocations",field:"count"},{match:"function.duration_ms",meter:"function.gb_seconds",scale:0.001},{match:"build.duration_ms",meter:"build.minutes",scale:0.000016666666666666667},{match:"telemetry.ingest_bytes",meter:"telemetry.ingest_gb",scale:1/we},{match:"image.transform",meter:"image.transformations",field:"count"}];function An(e,t){return e.match.endsWith("*")?t.startsWith(e.match.slice(0,-1)):e.match===t}function Yp(e,t=xd){return t.find((r)=>!r.match.endsWith("*")&&r.match===e)??t.find((r)=>An(r,e))}function On(e,t){let r=t.field??"value",n=r==="count"?1:r==="bytesOut"?e.bytesOut:r==="bytesIn"?e.bytesIn:r==="durationMs"?e.durationMs:e.value;if(n==null||!Number.isFinite(n))return;return n*(t.scale??1)}function Zp(e,t){return Cn("sha256").update([t,e.meter,e.organizationId,e.projectId??"",e.environmentId??"",e.resourceId??"",e.timestamp].join("\x00")).digest("hex").slice(0,32)}class Po{resetToleranceRatio;last=new Map;constructor(e=0.999){this.resetToleranceRatio=e}delta(e,t,r=new Date){if(!Number.isFinite(t)||t<0)return;let n=new Date(r).getTime(),o=this.last.get(e);if(!o)return this.last.set(e,{value:t,at:n}),t>0?t:void 0;if(n<o.at)return;if(t<o.value&&t>=o.value*this.resetToleranceRatio)return;if(this.last.set(e,{value:t,at:n}),t>=o.value){let a=t-o.value;return a>0?a:void 0}return t>0?t:void 0}prune(e){let t=e.getTime(),r=0;for(let[n,o]of this.last)if(o.at<t)this.last.delete(n),r++;return r}get size(){return this.last.size}}function Ht(e,t){let r=e[t];return typeof r==="string"&&r.length>0?r:void 0}function Od(e,t,r={}){let n=r.mappings??xd,o=r.counters,a=[];for(let d of t){let u=Yp(d.name,n);if(!u)continue;let p=On(d,u);if(p==null)continue;if(u.cumulative){if(!o)continue;let g=[d.projectId,d.environmentId??"",d.resourceId??"",d.name,d.source].join("\x00"),m=o.delta(g,p,d.timestamp);if(m==null)continue;p=m}if(!(p>0))continue;let E={organizationId:e,projectId:d.projectId,environmentId:d.environmentId,resourceId:d.resourceId,provider:Ht(d.attributes,"provider")??r.defaultProvider,region:d.region??Ht(d.attributes,"region"),meter:u.meter,quantity:p,timestamp:d.timestamp,attributes:{source:d.source,signal:d.name}};a.push({...E,key:Zp(E,d.id)})}return a}function _d(e){let t=new Map;for(let r of e){let n=new Date(Math.floor(new Date(r.timestamp).getTime()/3600000)*3600000).toISOString(),o=[r.organizationId,r.projectId??"",r.environmentId??"",r.resourceId??"",r.provider??"",r.region??"",r.meter,n].join("\x00"),a=t.get(o);if(a)a.quantity+=r.quantity;else t.set(o,{...r,timestamp:n})}return[...t.values()]}import{createHash as Un}from"node:crypto";var ue=(e)=>{if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}},H=(e)=>typeof e==="string"&&e!==""?e:void 0,ke=(e)=>Number(e)===1,Bt=(e)=>e==null?void 0:Number(e);function Vt(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:H(e.project_id),environmentId:H(e.environment_id),name:String(e.name),period:String(e.period),timezone:String(e.timezone),currency:String(e.currency),softLimitCents:Bt(e.soft_limit_cents),hardLimitCents:Bt(e.hard_limit_cents),thresholds:ue(e.thresholds),meters:ue(e.meters),graceSeconds:Number(e.grace_seconds),hysteresisPercent:Number(e.hysteresis_percent),dryRun:ke(e.dry_run),enabled:ke(e.enabled),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function dt(e){return{id:String(e.id),budgetId:String(e.budget_id),organizationId:String(e.organization_id),projectId:H(e.project_id),environmentId:H(e.environment_id),action:String(e.action),state:String(e.state),reason:String(e.reason),restore:ue(e.restore),triggeredAtPercent:Number(e.triggered_at_percent),simulated:ke(e.simulated),appliedAt:H(e.applied_at),releasedAt:H(e.released_at),error:H(e.error),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Kt(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:H(e.project_id),environmentId:H(e.environment_id),signal:String(e.signal),direction:String(e.direction),observed:Number(e.observed),expected:Number(e.expected),score:Number(e.score),deltaPercent:Number(e.delta_percent),severity:String(e.severity),bucketStart:String(e.bucket_start),evidence:ue(e.evidence),acknowledgedAt:H(e.acknowledged_at),createdAt:String(e.created_at)}}function Dn(e){return{organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:String(e.environment_id),resourceId:String(e.resource_id),provider:String(e.provider),region:String(e.region),meter:String(e.meter),bucketStart:String(e.bucket_start),quantity:Number(e.quantity),costCents:Number(e.cost_cents),sampleCount:Number(e.sample_count),updatedAt:String(e.updated_at)}}function Dt(e,t,r){return[e,t??"",r??""].join("/")}var em=[{atPercent:50,actions:["notify"]},{atPercent:80,actions:["notify"]},{atPercent:100,actions:["notify"],onProjection:!0},{atPercent:100,actions:["notify","block_builds","block_deployments"]},{atPercent:115,actions:["notify","block_builds","block_deployments","throttle_requests"]}];class Fi{controlPlane;options;constructor(e,t={}){this.controlPlane=e;this.options=t}now(){return(this.options.now?.()??new Date).toISOString()}get priceBook(){return this.options.priceBook??Nd}query(e,t=[]){return this.controlPlane.database.query(e).all(...t)}createBudget(e){let t=e.name.trim();if(!t)throw Error("Budgets require a name.");if(e.softLimitCents==null&&e.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(e.softLimitCents!=null&&e.hardLimitCents!=null&&e.softLimitCents>e.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");let r=e.timezone??"UTC";if(!Mi(r))throw Error(`Unknown timezone: ${r}`);let n=(e.thresholds??[...em]).filter((d)=>Number.isFinite(d.atPercent)&&d.atPercent>=0);if(e.environmentId&&!e.projectId)throw Error("An environment-scoped budget must also name its project.");let o=crypto.randomUUID(),a=this.now();return this.controlPlane.database.run("INSERT INTO spend_budgets (id,organization_id,project_id,environment_id,name,period,timezone,currency,soft_limit_cents,hard_limit_cents,thresholds,meters,grace_seconds,hysteresis_percent,dry_run,enabled,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?,?)",[o,e.organizationId,e.projectId??null,e.environmentId??null,t,e.period,r,e.currency??"USD",e.softLimitCents??null,e.hardLimitCents??null,JSON.stringify(n),JSON.stringify(e.meters??[]),Math.max(0,Math.floor(e.graceSeconds??0)),Math.max(0,e.hysteresisPercent??5),e.dryRun?1:0,e.enabled===!1?0:1,a,a]),this.getBudget(o)}getBudget(e){let t=this.query("SELECT * FROM spend_budgets WHERE id = ?",[e])[0];return t?Vt(t):void 0}listBudgets(e){let t=["organization_id = ?"],r=[e.organizationId];if(e.projectId)t.push("(project_id IS NULL OR project_id = ?)"),r.push(e.projectId);if(e.enabledOnly)t.push("enabled = 1");return this.query(`SELECT * FROM spend_budgets WHERE ${t.join(" AND ")} ORDER BY created_at`,r).map(Vt)}budgetsForScope(e,t,r){return this.listBudgets({organizationId:e,enabledOnly:!0}).filter((n)=>{if(n.projectId&&n.projectId!==t)return!1;if(n.environmentId&&n.environmentId!==r)return!1;return!0}).sort((n,o)=>Number(!!n.projectId)-Number(!!o.projectId)||Number(!!n.environmentId)-Number(!!o.environmentId))}updateBudget(e,t,r){let n=this.getBudget(e);if(!n)throw Error("Budget was not found.");if(r!=null&&r!==n.version)throw Error(`Budget was modified concurrently (expected version ${r}, found ${n.version}).`);let o={...n,...t};if(o.softLimitCents==null&&o.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(o.softLimitCents!=null&&o.hardLimitCents!=null&&o.softLimitCents>o.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");if(t.timezone&&!Mi(t.timezone))throw Error(`Unknown timezone: ${t.timezone}`);return this.controlPlane.database.run("UPDATE spend_budgets SET name=?,period=?,timezone=?,currency=?,soft_limit_cents=?,hard_limit_cents=?,thresholds=?,meters=?,grace_seconds=?,hysteresis_percent=?,dry_run=?,enabled=?,version=version+1,updated_at=? WHERE id=?",[o.name,o.period,o.timezone,o.currency??"USD",o.softLimitCents??null,o.hardLimitCents??null,JSON.stringify(o.thresholds??[]),JSON.stringify(o.meters??[]),Math.max(0,Math.floor(o.graceSeconds??0)),Math.max(0,o.hysteresisPercent??5),o.dryRun?1:0,o.enabled===!1?0:1,this.now(),e]),this.getBudget(e)}deleteBudget(e){return this.controlPlane.database.run("DELETE FROM spend_budgets WHERE id = ?",[e]).changes>0}ingestUsage(e){let t={applied:0,duplicates:0,costCents:0,unpricedMeters:[]},r=new Set,n=this.now();return this.controlPlane.database.transaction((a)=>{for(let d of a){if(!(d.quantity>0)||!Number.isFinite(d.quantity))continue;let u=d.key??this.deltaFallbackKey(d);if(this.controlPlane.database.run("INSERT OR IGNORE INTO spend_usage_receipts (key,organization_id,bucket_start,created_at) VALUES (?,?,?,?)",[u,d.organizationId,en(d.timestamp),n]).changes===0){t.duplicates++;continue}let E={projectId:d.projectId??"",environmentId:d.environmentId??"",resourceId:d.resourceId??"",provider:d.provider??"",region:d.region??""},g=this.periodQuantity(d),m=Ro(this.priceBook,{meter:d.meter,quantity:d.quantity,provider:d.provider,region:d.region},g);if(m.unpriced)r.add(String(d.meter));this.controlPlane.database.run(`INSERT INTO spend_usage (organization_id,project_id,environment_id,resource_id,provider,region,meter,bucket_start,quantity,cost_cents,sample_count,updated_at)
1568
1568
  VALUES (?,?,?,?,?,?,?,?,?,?,1,?)
@@ -1614,4 +1614,4 @@ TS_CLOUD_THROTTLE_EOF`);return ge("applying the throttled firewall ruleset",d),{
1614
1614
  ${o}
1615
1615
  TS_CLOUD_THROTTLE_EOF`);ge("restoring the firewall ruleset",a)}}function ey(e){let t=async(n,o)=>{let a={},d,u=0;for(let[p,E]of e.entries()){let g=E[n];if(!g)continue;u++;try{a[String(p)]=await g.call(E,o)}catch(m){a[String(p)]={error:m instanceof Error?m.message:String(m)},d??=m}}if(u===0)throw Error(`No transport implements ${n}.`);if(d)throw d;return{kind:"composite",legs:a}},r=async(n,o)=>{let a=o.legs??{},d;for(let[u,p]of e.entries()){let E=p[n];if(!E)continue;let g=a[String(u)];if(!g||typeof g!=="object"||Array.isArray(g)||"error"in g)continue;try{await E.call(p,g)}catch(m){d??=m}}if(d)throw d};return{throttleRequests:(n)=>t("throttleRequests",n),restoreRequests:(n)=>r("restoreRequests",n),suspendFunctions:(n)=>t("suspendFunctions",n),resumeFunctions:(n)=>r("resumeFunctions",n),serveStatic:(n)=>t("serveStatic",n),restoreDynamic:(n)=>r("restoreDynamic",n),suspendProject:(n)=>t("suspendProject",n),resumeProject:(n)=>r("resumeProject",n)}}import{createHash as vi}from"node:crypto";class i extends Error{code;status;details;constructor(e,t,r,n){super(t);this.code=e;this.status=r;this.details=n}}function gt(e,t){if(e.organizationId!==t.organizationId)return!1;if(e.projectId&&e.projectId!==t.projectId)return!1;if(e.environmentId&&e.environmentId!==t.environmentId)return!1;if(e.resourceId&&e.resourceId!==t.resourceId)return!1;return!0}function ty(e,t,r){return vi("sha256").update(`${e.toUpperCase()}
1616
1616
  ${t}
1617
- ${JSON.stringify(r)}`).digest("hex")}class Ki{controlPlane;identities;queue;spendGate;constructor(e,t){this.controlPlane=e;this.identities=t;this.queue=new c(e),this.spendGate=new nn(e)}target(e,t){let r=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,t),n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope);if(!r||!n||!gt(n,r))throw new i("forbidden","The token does not grant access to this resource.",403);return r}authorize(e,t,r){if(!e.token.capabilities.includes(t))throw new i("forbidden",`The token is missing the ${t} capability.`,403);let n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,r),o=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope),a=t==="project:read"&&!!n&&!!o&&gt(n,o);if(!n||!o||!gt(o,n)&&!a)throw new i("forbidden","The token does not grant access to this resource.",403);let d=a?o:n;if(!x({membership:e.membership,grants:this.controlPlane.listGrants(e.membership.id),capability:t,target:d}).allowed)throw new i("forbidden","The service account does not have access to this resource.",403);return n}listProjects(e){return this.controlPlane.listProjects().filter((t)=>t.organizationId===e.serviceAccount.organizationId).filter((t)=>{try{return this.authorize(e,"project:read",{type:"project",id:t.id}),!0}catch{return!1}}).map((t)=>({id:t.id,slug:t.slug,name:t.name,description:t.description,version:t.version,createdAt:t.createdAt,updatedAt:t.updatedAt}))}listEnvironments(e,t){let r=this.controlPlane.getProject(t);if(!r||r.organizationId!==e.serviceAccount.organizationId)throw new i("not_found","Project was not found.",404);return this.controlPlane.listEnvironments(t).filter((n)=>{try{return this.authorize(e,"project:read",{type:"environment",id:n.id}),!0}catch{return!1}}).map((n)=>({id:n.id,projectId:n.projectId,slug:n.slug,name:n.name,kind:n.kind,region:n.region,version:n.version,createdAt:n.createdAt,updatedAt:n.updatedAt}))}listServices(e,t,r){let n=new Set(this.listEnvironments(e,t).map((o)=>String(o.id)));if(r&&!n.has(r))throw new i("not_found","Environment was not found.",404);return this.controlPlane.listResources(t,r).filter((o)=>!o.environmentId||n.has(o.environmentId)).filter((o)=>{try{return this.authorize(e,"project:read",{type:"resource",id:o.id}),!0}catch{return!1}}).map((o)=>({id:o.id,projectId:o.projectId,environmentId:o.environmentId,kind:o.kind,slug:o.slug,name:o.name,provider:o.provider,providerId:o.providerId,metadata:s(o.metadata),version:o.version,createdAt:o.createdAt,updatedAt:o.updatedAt}))}listOperations(e,t){return this.controlPlane.listOperations({projectId:t,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.environmentId?{type:"environment",id:n.environmentId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.authorize(e,"deployments:read",o),!0}catch{return!1}}).map((n)=>this.operation(n))}listEvents(e,t,r){if(t)this.authorize(e,"audit:read",{type:"project",id:t});else this.authorize(e,"audit:read",e.token.scope);return this.controlPlane.listEvents({organizationId:e.serviceAccount.organizationId,projectId:t,afterSequence:r,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.target(e,o),!0}catch{return!1}}).map((n)=>({id:n.id,sequence:n.sequence,projectId:n.projectId,operationId:n.operationId,resourceId:n.resourceId,correlationId:n.correlationId,type:n.type,level:n.level,payload:s(n.payload),createdAt:n.createdAt}))}createDeployment(e,t,r){if(!this.controlPlane.listEnvironments(t.projectId).find((g)=>g.id===t.environmentId))throw new i("not_found","Environment was not found in this project.",404);let o=t.serviceId?{type:"resource",id:t.serviceId}:{type:"environment",id:t.environmentId};this.authorize(e,"deployments:create",o);let a=this.spendGate.check("deploy",{organizationId:e.serviceAccount.organizationId,projectId:t.projectId,environmentId:t.environmentId});if(!a.allowed)throw new i("spend_cap_exceeded",a.reason??"A spend cap is blocking deployments.",402,{action:a.action,budgetId:a.budgetId});let d=ty("POST","/api/v1/deployments",t),u=this.identities.getIdempotency(e.token.id,r);if(u){if(u.requestHash!==d)throw new i("idempotency_conflict","Idempotency-Key was already used for another request.",409);let g=u.operationId?this.controlPlane.getOperation(u.operationId):void 0;if(!g)throw new i("idempotency_unavailable","The original operation is no longer available.",409);return{operation:this.operation(g),replay:!0}}if(t.serviceId){let g=this.controlPlane.getResource(t.serviceId);if(!g||g.projectId!==t.projectId||g.environmentId!==t.environmentId)throw new i("not_found","Service was not found in this environment.",404)}let p=t.serviceId?this.controlPlane.getResource(t.serviceId):void 0,E=this.queue.enqueue({projectId:t.projectId,environmentId:t.environmentId,resourceId:t.serviceId,actorId:e.actor.id,kind:t.action==="rollback"?"deployment.rollback":"deployment.create",idempotencyKey:`api:${e.token.id}:${r}`,input:s({action:t.action??"deploy",revision:t.revision??null}),lockKey:t.serviceId?`resource:${t.serviceId}`:`environment:${t.environmentId}`,providerKey:p?.provider??"default",buildSlot:t.action!=="rollback",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.identities.saveIdempotency({tokenId:e.token.id,key:r,requestHash:d,operationId:E.id,responseStatus:202,responseBody:{operationId:E.id}}),{operation:this.operation(E),replay:!1}}operation(e){return{id:e.id,state:e.state,kind:e.kind,projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:e.actorId,correlationId:e.correlationId,input:s(e.input),output:s(e.output),error:e.error,attempt:e.attempt,createdAt:e.createdAt,updatedAt:e.updatedAt,startedAt:e.startedAt,finishedAt:e.finishedAt}}}function ze(e){return e.serviceAccount.organizationId}function hr(e){if(e==null)return;if(e==="daily"||e==="weekly"||e==="monthly")return e;throw new i("validation_error","period must be daily, weekly, or monthly.",422)}function ne(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r)||r<0||!Number.isInteger(r))throw new i("validation_error",`${t} must be a non-negative integer.`,422);return r}function X(e,t,r,n,o){if(o)e.authorization.authorize(t,r,{type:"environment",id:o});else if(n)e.authorization.authorize(t,r,{type:"project",id:n});else e.authorization.authorize(t,r,{type:"organization"});return{organizationId:ze(t),projectId:n,environmentId:o}}async function Uo(e,t,r){let{method:n,url:o}=r,a=e.now?.()??new Date,d=o.searchParams.get("projectId")??void 0,u=o.searchParams.get("environmentId")??void 0;if(n==="GET"&&o.pathname==="/api/v1/usage"){let T=X(e,t,"billing:read",d,u);return e.service.usageReport({...T,period:hr(o.searchParams.get("period")),timezone:o.searchParams.get("timezone")??void 0,now:a})}if(n==="GET"&&o.pathname==="/api/v1/usage/rollups"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("from"),_=o.searchParams.get("to");if(!h||!_)throw new i("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(h))||Number.isNaN(Date.parse(_)))throw new i("validation_error","from and to must be ISO-8601 timestamps.",422);let N=o.searchParams.getAll("meter");return{data:e.store.listRollups({...T,from:h,to:_,meters:N.length>0?N:void 0},ne(o.searchParams.get("limit"),"limit")??1000)}}if(n==="GET"&&o.pathname==="/api/v1/usage/focus"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("from"),_=o.searchParams.get("to");if(!h||!_)throw new i("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(h))||Number.isNaN(Date.parse(_)))throw new i("validation_error","from and to must be ISO-8601 timestamps.",422);if(new Date(_).getTime()-new Date(h).getTime()>31622400000)throw new i("validation_error","The range must not exceed one year.",422);let N=o.searchParams.get("granularity")==="hourly"?"hourly":"daily",y=e.store.listRollups({...T,from:h,to:_},1e4),L=qd(y,{billingPeriodStart:h,billingPeriodEnd:_,currency:e.store.priceBook.currency,granularity:N});return{contentType:"application/x-ndjson",body:Lo(L),recordCount:L.length}}if(n==="GET"&&o.pathname==="/api/v1/spend/budgets"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listBudgets({organizationId:T.organizationId,projectId:T.projectId})}}if(n==="POST"&&o.pathname==="/api/v1/spend/budgets"){let T=await r.body?.()??{},_={organizationId:X(e,t,"billing:manage",T.projectId,T.environmentId).organizationId,projectId:T.projectId,environmentId:T.environmentId,name:String(T.name??"").trim(),period:hr(T.period??"monthly")??"monthly",timezone:T.timezone,currency:T.currency,softLimitCents:ne(T.softLimitCents,"softLimitCents"),hardLimitCents:ne(T.hardLimitCents,"hardLimitCents"),thresholds:T.thresholds,meters:T.meters,graceSeconds:ne(T.graceSeconds,"graceSeconds"),hysteresisPercent:T.hysteresisPercent,dryRun:T.dryRun!==!1,enabled:T.enabled};try{return{data:e.store.createBudget(_)}}catch(N){throw new i("validation_error",N instanceof Error?N.message:String(N),422)}}let p=/^\/api\/v1\/spend\/budgets\/([^/]+)$/.exec(o.pathname);if(p&&(n==="PATCH"||n==="DELETE")){let T=e.store.getBudget(decodeURIComponent(p[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Budget was not found.",404);if(X(e,t,"billing:manage",T.projectId,T.environmentId),n==="DELETE")return{data:{deleted:e.store.deleteBudget(T.id)}};let h=await r.body?.()??{};try{return{data:e.store.updateBudget(T.id,h,ne(h.expectedVersion,"expectedVersion"))}}catch(_){let N=_ instanceof Error?_.message:String(_);throw new i(N.includes("concurrently")?"conflict":"validation_error",N,N.includes("concurrently")?409:422)}}if(n==="GET"&&o.pathname==="/api/v1/spend/anomalies"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listAnomalies({organizationId:T.organizationId,projectId:T.projectId,since:o.searchParams.get("since")??void 0,unacknowledgedOnly:o.searchParams.get("unacknowledged")==="true",limit:ne(o.searchParams.get("limit"),"limit")})}}let E=/^\/api\/v1\/spend\/anomalies\/([^/]+)\/acknowledge$/.exec(o.pathname);if(E&&n==="POST"){let T=e.store.getAnomaly(decodeURIComponent(E[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Anomaly was not found.",404);return X(e,t,"billing:manage",T.projectId,T.environmentId),{data:{acknowledged:e.store.acknowledgeAnomaly(T.id)}}}if(n==="GET"&&o.pathname==="/api/v1/spend/signals")return X(e,t,"billing:read",d,u),{data:rn};if(o.pathname==="/api/v1/spend/anomaly-configs"){if(n==="GET"){let T=X(e,t,"billing:read",d,u);return{data:e.service.anomalyConfigs.list({organizationId:T.organizationId,projectId:T.projectId})}}if(n==="POST"){let T=await r.body?.()??{},h=X(e,t,"billing:manage",T.projectId,T.environmentId);try{return{data:e.service.anomalyConfigs.upsert({organizationId:h.organizationId,projectId:T.projectId,environmentId:T.environmentId,signal:String(T.signal??""),enabled:T.enabled,sensitivity:T.sensitivity,seasonLength:T.seasonLength==null?void 0:Number(T.seasonLength),minAbsoluteDelta:T.minAbsoluteDelta==null?void 0:Number(T.minAbsoluteDelta),detectDrops:T.detectDrops,severity:T.severity})}}catch(_){throw new i("validation_error",_ instanceof Error?_.message:String(_),422)}}}let g=/^\/api\/v1\/spend\/anomaly-configs\/([^/]+)$/.exec(o.pathname);if(g&&n==="DELETE"){let T=e.service.anomalyConfigs.get(decodeURIComponent(g[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Anomaly config was not found.",404);return X(e,t,"billing:manage",T.projectId,T.environmentId),{data:{deleted:e.service.anomalyConfigs.delete(T.id)}}}if(o.pathname==="/api/v1/spend/anomaly-silences"){if(n==="GET"){let T=X(e,t,"billing:read",d,u);return{data:e.service.anomalyConfigs.listSilences({organizationId:T.organizationId,projectId:T.projectId,includeExpired:o.searchParams.get("includeExpired")==="true"})}}if(n==="POST"){let T=await r.body?.()??{},h=X(e,t,"billing:manage",T.projectId);try{return{data:e.service.anomalyConfigs.silence({organizationId:h.organizationId,projectId:T.projectId,signal:T.signal,routePattern:T.routePattern,statusCode:T.statusCode==null?void 0:Number(T.statusCode),reason:String(T.reason??""),expiresAt:T.expiresAt})}}catch(_){throw new i("validation_error",_ instanceof Error?_.message:String(_),422)}}}let m=/^\/api\/v1\/spend\/anomaly-silences\/([^/]+)$/.exec(o.pathname);if(m&&n==="DELETE")return X(e,t,"billing:manage",d),{data:{deleted:e.service.anomalyConfigs.removeSilence(decodeURIComponent(m[1]))}};if(n==="GET"&&o.pathname==="/api/v1/spend/enforcement"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listEnforcements({organizationId:T.organizationId,activeOnly:o.searchParams.get("active")!=="false"})}}if(n==="GET"&&o.pathname==="/api/v1/spend/allowance"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("operation")??"deploy";if(!["build","deploy","function_invoke","request"].includes(h))throw new i("validation_error","operation must be build, deploy, function_invoke, or request.",422);let N=e.store.listEnforcements({organizationId:T.organizationId,activeOnly:!0}).filter((I)=>(!I.projectId||I.projectId===T.projectId)&&(!I.environmentId||I.environmentId===T.environmentId)),y=Hd(h,N),v=e.store.budgetsForScope(T.organizationId,T.projectId,T.environmentId).map((I)=>e.service.status(I,a));return{operation:h,allowed:y.allowed,blockedBy:y.blockedBy??null,reason:y.reason??null,budgets:v.map((I)=>({id:I.budget.id,name:I.budget.name,usedPercent:I.decision.usedPercent,projectedPercent:I.decision.projectedPercent,level:I.decision.level,timeToCap:I.timeToCap}))}}return}function Qo(){let e=[{name:"projectId",in:"query",schema:{type:"string"}},{name:"environmentId",in:"query",schema:{type:"string"}}];return{"/api/v1/usage":{get:{summary:"Current usage, cost, and every budget governing the scope.",parameters:[...e,{name:"period",in:"query",schema:{type:"string",enum:["daily","weekly","monthly"]}},{name:"timezone",in:"query",schema:{type:"string"}}],responses:{"200":{description:"Usage totals, per-meter breakdown, hourly series, and budget status."}}}},"/api/v1/usage/rollups":{get:{summary:"Itemized hourly usage rollups.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"meter",in:"query",schema:{type:"array",items:{type:"string"}}},{name:"limit",in:"query",schema:{type:"integer"}}],responses:{"200":{description:"Hourly rollups, newest first."}}}},"/api/v1/usage/focus":{get:{summary:"Usage and cost in FOCUS v1.3 format, newline-delimited JSON.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"granularity",in:"query",schema:{type:"string",enum:["daily","hourly"]}}],responses:{"200":{description:"FOCUS records, one JSON object per line."}}}},"/api/v1/spend/budgets":{get:{summary:"Budgets governing a scope.",parameters:e,responses:{"200":{description:"Budgets."}}},post:{summary:"Create a budget. Starts in dry run unless dryRun is explicitly false.",responses:{"201":{description:"The created budget."},"422":{description:"Validation error."}}}},"/api/v1/spend/budgets/{budgetId}":{patch:{summary:"Update a budget. Pass expectedVersion for optimistic concurrency.",responses:{"200":{description:"The updated budget."},"409":{description:"Version conflict."}}},delete:{summary:"Delete a budget.",responses:{"200":{description:"Deletion result."}}}},"/api/v1/spend/anomalies":{get:{summary:"Detected spend anomalies.",parameters:[...e,{name:"since",in:"query",schema:{type:"string",format:"date-time"}},{name:"unacknowledged",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Anomalies, newest first."}}}},"/api/v1/spend/anomalies/{anomalyId}/acknowledge":{post:{summary:"Acknowledge an anomaly.",responses:{"200":{description:"Acknowledgement result."}}}},"/api/v1/spend/signals":{get:{summary:"Signals anomaly detection can run on, with their gap and sample rules.",responses:{"200":{description:"Signal catalog."}}}},"/api/v1/spend/anomaly-configs":{get:{summary:"Anomaly detection configuration.",parameters:e,responses:{"200":{description:"Configs."}}},post:{summary:"Create or update the config for a signal.",responses:{"200":{description:"The config."}}}},"/api/v1/spend/anomaly-configs/{configId}":{delete:{summary:"Delete an anomaly config, returning the signal to its default.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/anomaly-silences":{get:{summary:"Active anomaly silences.",parameters:e,responses:{"200":{description:"Silences."}}},post:{summary:"Silence a signal, route, or status code. A reason is required.",responses:{"200":{description:"The silence."}}}},"/api/v1/spend/anomaly-silences/{silenceId}":{delete:{summary:"Remove a silence.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/enforcement":{get:{summary:"Enforcement actions in force.",parameters:[...e,{name:"active",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Enforcement records."}}}},"/api/v1/spend/allowance":{get:{summary:"Whether an operation is allowed under current spend enforcement.",parameters:[...e,{name:"operation",in:"query",schema:{type:"string",enum:["build","deploy","function_invoke","request"]}}],responses:{"200":{description:"Allowance verdict and the budgets behind it."}}}}}}export{Je,yd,be,nr,Sd,x,ir,wt,Id,yo,DA,Wp,bd,s,Li,So,Wr,Cd,Ed,Jr,PA,vd,xI,OI,Io,_I,LI,Td,wd,$i,bo,ae,c,Co,Xe,Xr,kA,NA,Rd,BA,Eo,xA,OA,vo,Dd,Yr,To,_A,sr,Pd,Jp,or,Zr,LA,wo,$A,O,MA,kd,Xp,Ro,FA,UA,QA,Nd,Mi,Do,Bd,ar,Rt,HA,en,GA,xd,Yp,Zp,Po,Od,_d,Dt,em,Fi,Ld,ko,tn,tm,Ui,$d,Md,Qi,rm,Fd,Ud,Qd,Hd,No,nm,im,VA,sm,Gd,Hi,om,am,Bo,rn,xo,Oo,_o,Vd,cm,qd,Lo,qA,cr,jA,jd,nn,zd,zA,Kd,dm,Gi,sn,$o,Vi,Ye,KA,lm,um,dr,Wd,Jd,Xd,qi,ji,zi,WA,JA,Pt,Mo,XA,on,gm,Fo,YA,pm,mm,fm,ZA,hm,Am,ey,i,ty,Ki,Uo,Qo};
1617
+ ${JSON.stringify(r)}`).digest("hex")}class Ki{controlPlane;identities;queue;spendGate;constructor(e,t){this.controlPlane=e;this.identities=t;this.queue=new c(e),this.spendGate=new nn(e)}target(e,t){let r=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,t),n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope);if(!r||!n||!gt(n,r))throw new i("forbidden","The token does not grant access to this resource.",403);return r}authorize(e,t,r){if(!e.token.capabilities.includes(t))throw new i("forbidden",`The token is missing the ${t} capability.`,403);let n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,r),o=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope),a=t==="project:read"&&!!n&&!!o&&gt(n,o);if(!n||!o||!gt(o,n)&&!a)throw new i("forbidden","The token does not grant access to this resource.",403);let d=a?o:n;if(!x({membership:e.membership,grants:this.controlPlane.listGrants(e.membership.id),capability:t,target:d}).allowed)throw new i("forbidden","The service account does not have access to this resource.",403);return n}listProjects(e){return this.controlPlane.listProjects().filter((t)=>t.organizationId===e.serviceAccount.organizationId).filter((t)=>{try{return this.authorize(e,"project:read",{type:"project",id:t.id}),!0}catch{return!1}}).map((t)=>({id:t.id,slug:t.slug,name:t.name,description:t.description,version:t.version,createdAt:t.createdAt,updatedAt:t.updatedAt}))}listEnvironments(e,t){let r=this.controlPlane.getProject(t);if(!r||r.organizationId!==e.serviceAccount.organizationId)throw new i("not_found","Project was not found.",404);return this.controlPlane.listEnvironments(t).filter((n)=>{try{return this.authorize(e,"project:read",{type:"environment",id:n.id}),!0}catch{return!1}}).map((n)=>({id:n.id,projectId:n.projectId,slug:n.slug,name:n.name,kind:n.kind,region:n.region,version:n.version,createdAt:n.createdAt,updatedAt:n.updatedAt}))}listServices(e,t,r){let n=new Set(this.listEnvironments(e,t).map((o)=>String(o.id)));if(r&&!n.has(r))throw new i("not_found","Environment was not found.",404);return this.controlPlane.listResources(t,r).filter((o)=>!o.environmentId||n.has(o.environmentId)).filter((o)=>{try{return this.authorize(e,"project:read",{type:"resource",id:o.id}),!0}catch{return!1}}).map((o)=>({id:o.id,projectId:o.projectId,environmentId:o.environmentId,kind:o.kind,slug:o.slug,name:o.name,provider:o.provider,providerId:o.providerId,metadata:s(o.metadata),version:o.version,createdAt:o.createdAt,updatedAt:o.updatedAt}))}listOperations(e,t){return this.controlPlane.listOperations({projectId:t,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.environmentId?{type:"environment",id:n.environmentId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.authorize(e,"deployments:read",o),!0}catch{return!1}}).map((n)=>this.operation(n))}listEvents(e,t,r){if(t)this.authorize(e,"audit:read",{type:"project",id:t});else this.authorize(e,"audit:read",e.token.scope);return this.controlPlane.listEvents({organizationId:e.serviceAccount.organizationId,projectId:t,afterSequence:r,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.target(e,o),!0}catch{return!1}}).map((n)=>({id:n.id,sequence:n.sequence,projectId:n.projectId,operationId:n.operationId,resourceId:n.resourceId,correlationId:n.correlationId,type:n.type,level:n.level,payload:s(n.payload),createdAt:n.createdAt}))}createDeployment(e,t,r){if(!this.controlPlane.listEnvironments(t.projectId).find((g)=>g.id===t.environmentId))throw new i("not_found","Environment was not found in this project.",404);let o=t.serviceId?{type:"resource",id:t.serviceId}:{type:"environment",id:t.environmentId};this.authorize(e,"deployments:create",o);let a=this.spendGate.check("deploy",{organizationId:e.serviceAccount.organizationId,projectId:t.projectId,environmentId:t.environmentId});if(!a.allowed)throw new i("spend_cap_exceeded",a.reason??"A spend cap is blocking deployments.",402,{action:a.action,budgetId:a.budgetId});let d=ty("POST","/api/v1/deployments",t),u=this.identities.getIdempotency(e.token.id,r);if(u){if(u.requestHash!==d)throw new i("idempotency_conflict","Idempotency-Key was already used for another request.",409);let g=u.operationId?this.controlPlane.getOperation(u.operationId):void 0;if(!g)throw new i("idempotency_unavailable","The original operation is no longer available.",409);return{operation:this.operation(g),replay:!0}}if(t.serviceId){let g=this.controlPlane.getResource(t.serviceId);if(!g||g.projectId!==t.projectId||g.environmentId!==t.environmentId)throw new i("not_found","Service was not found in this environment.",404)}let p=t.serviceId?this.controlPlane.getResource(t.serviceId):void 0,E=this.queue.enqueue({projectId:t.projectId,environmentId:t.environmentId,resourceId:t.serviceId,actorId:e.actor.id,kind:t.action==="rollback"?"deployment.rollback":"deployment.create",idempotencyKey:`api:${e.token.id}:${r}`,input:s({action:t.action??"deploy",revision:t.revision??null}),lockKey:t.serviceId?`resource:${t.serviceId}`:`environment:${t.environmentId}`,providerKey:p?.provider??"default",buildSlot:t.action!=="rollback",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.identities.saveIdempotency({tokenId:e.token.id,key:r,requestHash:d,operationId:E.id,responseStatus:202,responseBody:{operationId:E.id}}),{operation:this.operation(E),replay:!1}}operation(e){return{id:e.id,state:e.state,kind:e.kind,projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:e.actorId,correlationId:e.correlationId,input:s(e.input),output:s(e.output),error:e.error,attempt:e.attempt,createdAt:e.createdAt,updatedAt:e.updatedAt,startedAt:e.startedAt,finishedAt:e.finishedAt}}}function ze(e){return e.serviceAccount.organizationId}function hr(e){if(e==null)return;if(e==="daily"||e==="weekly"||e==="monthly")return e;throw new i("validation_error","period must be daily, weekly, or monthly.",422)}function ne(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r)||r<0||!Number.isInteger(r))throw new i("validation_error",`${t} must be a non-negative integer.`,422);return r}function X(e,t,r,n,o){if(o)e.authorization.authorize(t,r,{type:"environment",id:o});else if(n)e.authorization.authorize(t,r,{type:"project",id:n});else e.authorization.authorize(t,r,{type:"organization"});return{organizationId:ze(t),projectId:n,environmentId:o}}async function Uo(e,t,r){let{method:n,url:o}=r,a=e.now?.()??new Date,d=o.searchParams.get("projectId")??void 0,u=o.searchParams.get("environmentId")??void 0;if(n==="GET"&&o.pathname==="/api/v1/usage"){let T=X(e,t,"billing:read",d,u);return e.service.usageReport({...T,period:hr(o.searchParams.get("period")),timezone:o.searchParams.get("timezone")??void 0,now:a})}if(n==="GET"&&o.pathname==="/api/v1/usage/rollups"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("from"),_=o.searchParams.get("to");if(!h||!_)throw new i("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(h))||Number.isNaN(Date.parse(_)))throw new i("validation_error","from and to must be ISO-8601 timestamps.",422);let N=o.searchParams.getAll("meter");return{data:e.store.listRollups({...T,from:h,to:_,meters:N.length>0?N:void 0},ne(o.searchParams.get("limit"),"limit")??1000)}}if(n==="GET"&&o.pathname==="/api/v1/usage/focus"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("from"),_=o.searchParams.get("to");if(!h||!_)throw new i("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(h))||Number.isNaN(Date.parse(_)))throw new i("validation_error","from and to must be ISO-8601 timestamps.",422);if(new Date(_).getTime()-new Date(h).getTime()>31622400000)throw new i("validation_error","The range must not exceed one year.",422);let N=o.searchParams.get("granularity")==="hourly"?"hourly":"daily",y=e.store.listRollups({...T,from:h,to:_},1e4),L=qd(y,{billingPeriodStart:h,billingPeriodEnd:_,currency:e.store.priceBook.currency,granularity:N});return{contentType:"application/x-ndjson",body:Lo(L),recordCount:L.length}}if(n==="GET"&&o.pathname==="/api/v1/spend/budgets"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listBudgets({organizationId:T.organizationId,projectId:T.projectId})}}if(n==="POST"&&o.pathname==="/api/v1/spend/budgets"){let T=await r.body?.()??{},_={organizationId:X(e,t,"billing:manage",T.projectId,T.environmentId).organizationId,projectId:T.projectId,environmentId:T.environmentId,name:String(T.name??"").trim(),period:hr(T.period??"monthly")??"monthly",timezone:T.timezone,currency:T.currency,softLimitCents:ne(T.softLimitCents,"softLimitCents"),hardLimitCents:ne(T.hardLimitCents,"hardLimitCents"),thresholds:T.thresholds,meters:T.meters,graceSeconds:ne(T.graceSeconds,"graceSeconds"),hysteresisPercent:T.hysteresisPercent,dryRun:T.dryRun!==!1,enabled:T.enabled};try{return{data:e.store.createBudget(_)}}catch(N){throw new i("validation_error",N instanceof Error?N.message:String(N),422)}}let p=/^\/api\/v1\/spend\/budgets\/([^/]+)$/.exec(o.pathname);if(p&&(n==="PATCH"||n==="DELETE")){let T=e.store.getBudget(decodeURIComponent(p[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Budget was not found.",404);if(X(e,t,"billing:manage",T.projectId,T.environmentId),n==="DELETE")return{data:{deleted:e.store.deleteBudget(T.id)}};let h=await r.body?.()??{};try{return{data:e.store.updateBudget(T.id,h,ne(h.expectedVersion,"expectedVersion"))}}catch(_){let N=_ instanceof Error?_.message:String(_);throw new i(N.includes("concurrently")?"conflict":"validation_error",N,N.includes("concurrently")?409:422)}}if(n==="GET"&&o.pathname==="/api/v1/spend/anomalies"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listAnomalies({organizationId:T.organizationId,projectId:T.projectId,since:o.searchParams.get("since")??void 0,unacknowledgedOnly:o.searchParams.get("unacknowledged")==="true",limit:ne(o.searchParams.get("limit"),"limit")})}}let E=/^\/api\/v1\/spend\/anomalies\/([^/]+)\/acknowledge$/.exec(o.pathname);if(E&&n==="POST"){let T=e.store.getAnomaly(decodeURIComponent(E[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Anomaly was not found.",404);return X(e,t,"billing:manage",T.projectId,T.environmentId),{data:{acknowledged:e.store.acknowledgeAnomaly(T.id)}}}if(n==="GET"&&o.pathname==="/api/v1/spend/signals")return X(e,t,"billing:read",d,u),{data:rn};if(o.pathname==="/api/v1/spend/anomaly-configs"){if(n==="GET"){let T=X(e,t,"billing:read",d,u);return{data:e.service.anomalyConfigs.list({organizationId:T.organizationId,projectId:T.projectId})}}if(n==="POST"){let T=await r.body?.()??{},h=X(e,t,"billing:manage",T.projectId,T.environmentId);try{return{data:e.service.anomalyConfigs.upsert({organizationId:h.organizationId,projectId:T.projectId,environmentId:T.environmentId,signal:String(T.signal??""),enabled:T.enabled,sensitivity:T.sensitivity,seasonLength:T.seasonLength==null?void 0:Number(T.seasonLength),minAbsoluteDelta:T.minAbsoluteDelta==null?void 0:Number(T.minAbsoluteDelta),detectDrops:T.detectDrops,severity:T.severity})}}catch(_){throw new i("validation_error",_ instanceof Error?_.message:String(_),422)}}}let g=/^\/api\/v1\/spend\/anomaly-configs\/([^/]+)$/.exec(o.pathname);if(g&&n==="DELETE"){let T=e.service.anomalyConfigs.get(decodeURIComponent(g[1]));if(!T||T.organizationId!==ze(t))throw new i("not_found","Anomaly config was not found.",404);return X(e,t,"billing:manage",T.projectId,T.environmentId),{data:{deleted:e.service.anomalyConfigs.delete(T.id)}}}if(o.pathname==="/api/v1/spend/anomaly-silences"){if(n==="GET"){let T=X(e,t,"billing:read",d,u);return{data:e.service.anomalyConfigs.listSilences({organizationId:T.organizationId,projectId:T.projectId,includeExpired:o.searchParams.get("includeExpired")==="true"})}}if(n==="POST"){let T=await r.body?.()??{},h=X(e,t,"billing:manage",T.projectId);try{return{data:e.service.anomalyConfigs.silence({organizationId:h.organizationId,projectId:T.projectId,signal:T.signal,routePattern:T.routePattern,statusCode:T.statusCode==null?void 0:Number(T.statusCode),reason:String(T.reason??""),expiresAt:T.expiresAt})}}catch(_){throw new i("validation_error",_ instanceof Error?_.message:String(_),422)}}}let m=/^\/api\/v1\/spend\/anomaly-silences\/([^/]+)$/.exec(o.pathname);if(m&&n==="DELETE")return X(e,t,"billing:manage",d),{data:{deleted:e.service.anomalyConfigs.removeSilence(decodeURIComponent(m[1]))}};if(n==="GET"&&o.pathname==="/api/v1/spend/enforcement"){let T=X(e,t,"billing:read",d,u);return{data:e.store.listEnforcements({organizationId:T.organizationId,activeOnly:o.searchParams.get("active")!=="false"})}}if(n==="GET"&&o.pathname==="/api/v1/spend/allowance"){let T=X(e,t,"billing:read",d,u),h=o.searchParams.get("operation")??"deploy";if(!["build","deploy","function_invoke","request"].includes(h))throw new i("validation_error","operation must be build, deploy, function_invoke, or request.",422);let N=e.store.listEnforcements({organizationId:T.organizationId,activeOnly:!0}).filter((I)=>(!I.projectId||I.projectId===T.projectId)&&(!I.environmentId||I.environmentId===T.environmentId)),y=Hd(h,N),v=e.store.budgetsForScope(T.organizationId,T.projectId,T.environmentId).map((I)=>e.service.status(I,a));return{operation:h,allowed:y.allowed,blockedBy:y.blockedBy??null,reason:y.reason??null,budgets:v.map((I)=>({id:I.budget.id,name:I.budget.name,usedPercent:I.decision.usedPercent,projectedPercent:I.decision.projectedPercent,level:I.decision.level,timeToCap:I.timeToCap}))}}return}function Qo(){let e=[{name:"projectId",in:"query",schema:{type:"string"}},{name:"environmentId",in:"query",schema:{type:"string"}}];return{"/api/v1/usage":{get:{summary:"Current usage, cost, and every budget governing the scope.",parameters:[...e,{name:"period",in:"query",schema:{type:"string",enum:["daily","weekly","monthly"]}},{name:"timezone",in:"query",schema:{type:"string"}}],responses:{"200":{description:"Usage totals, per-meter breakdown, hourly series, and budget status."}}}},"/api/v1/usage/rollups":{get:{summary:"Itemized hourly usage rollups.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"meter",in:"query",schema:{type:"array",items:{type:"string"}}},{name:"limit",in:"query",schema:{type:"integer"}}],responses:{"200":{description:"Hourly rollups, newest first."}}}},"/api/v1/usage/focus":{get:{summary:"Usage and cost in FOCUS v1.3 format, newline-delimited JSON.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"granularity",in:"query",schema:{type:"string",enum:["daily","hourly"]}}],responses:{"200":{description:"FOCUS records, one JSON object per line."}}}},"/api/v1/spend/budgets":{get:{summary:"Budgets governing a scope.",parameters:e,responses:{"200":{description:"Budgets."}}},post:{summary:"Create a budget. Starts in dry run unless dryRun is explicitly false.",responses:{"201":{description:"The created budget."},"422":{description:"Validation error."}}}},"/api/v1/spend/budgets/{budgetId}":{patch:{summary:"Update a budget. Pass expectedVersion for optimistic concurrency.",responses:{"200":{description:"The updated budget."},"409":{description:"Version conflict."}}},delete:{summary:"Delete a budget.",responses:{"200":{description:"Deletion result."}}}},"/api/v1/spend/anomalies":{get:{summary:"Detected spend anomalies.",parameters:[...e,{name:"since",in:"query",schema:{type:"string",format:"date-time"}},{name:"unacknowledged",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Anomalies, newest first."}}}},"/api/v1/spend/anomalies/{anomalyId}/acknowledge":{post:{summary:"Acknowledge an anomaly.",responses:{"200":{description:"Acknowledgement result."}}}},"/api/v1/spend/signals":{get:{summary:"Signals anomaly detection can run on, with their gap and sample rules.",responses:{"200":{description:"Signal catalog."}}}},"/api/v1/spend/anomaly-configs":{get:{summary:"Anomaly detection configuration.",parameters:e,responses:{"200":{description:"Configs."}}},post:{summary:"Create or update the config for a signal.",responses:{"200":{description:"The config."}}}},"/api/v1/spend/anomaly-configs/{configId}":{delete:{summary:"Delete an anomaly config, returning the signal to its default.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/anomaly-silences":{get:{summary:"Active anomaly silences.",parameters:e,responses:{"200":{description:"Silences."}}},post:{summary:"Silence a signal, route, or status code. A reason is required.",responses:{"200":{description:"The silence."}}}},"/api/v1/spend/anomaly-silences/{silenceId}":{delete:{summary:"Remove a silence.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/enforcement":{get:{summary:"Enforcement actions in force.",parameters:[...e,{name:"active",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Enforcement records."}}}},"/api/v1/spend/allowance":{get:{summary:"Whether an operation is allowed under current spend enforcement.",parameters:[...e,{name:"operation",in:"query",schema:{type:"string",enum:["build","deploy","function_invoke","request"]}}],responses:{"200":{description:"Allowance verdict and the budgets behind it."}}}}}}export{Je,yd,Ce,nr,Sd,x,ir,wt,Id,yo,DA,Wp,bd,s,Li,So,Wr,Cd,Ed,Jr,PA,vd,xI,OI,Io,_I,LI,Td,wd,$i,bo,ce,c,Co,Xe,Xr,kA,NA,Rd,BA,Eo,xA,OA,vo,Dd,Yr,To,_A,sr,Pd,Jp,or,Zr,LA,wo,$A,O,MA,kd,Xp,Ro,FA,UA,QA,Nd,Mi,Do,Bd,ar,Rt,HA,en,GA,xd,Yp,Zp,Po,Od,_d,Dt,em,Fi,Ld,ko,tn,tm,Ui,$d,Md,Qi,rm,Fd,Ud,Qd,Hd,No,nm,im,VA,sm,Gd,Hi,om,am,Bo,rn,xo,Oo,_o,Vd,cm,qd,Lo,qA,cr,jA,jd,nn,zd,zA,Kd,dm,Gi,sn,$o,Vi,Ye,KA,lm,um,dr,Wd,Jd,Xd,qi,ji,zi,WA,JA,Pt,Mo,XA,on,gm,Fo,YA,pm,mm,fm,ZA,hm,Am,ey,i,ty,Ki,Uo,Qo};