@alchemy.run/fly 2.0.0-beta.84 → 2.0.0-beta.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 (307) hide show
  1. package/lib/App.d.ts +27 -5
  2. package/lib/App.d.ts.map +1 -1
  3. package/lib/App.js +29 -8
  4. package/lib/App.js.map +1 -1
  5. package/lib/AuthProvider.d.ts +1 -1
  6. package/lib/AuthProvider.d.ts.map +1 -1
  7. package/lib/AuthProvider.js.map +1 -1
  8. package/lib/BindService.d.ts +7 -7
  9. package/lib/BindService.d.ts.map +1 -1
  10. package/lib/BindService.js +21 -28
  11. package/lib/BindService.js.map +1 -1
  12. package/lib/Bootstrap.d.ts.map +1 -1
  13. package/lib/Bootstrap.js +2 -1
  14. package/lib/Bootstrap.js.map +1 -1
  15. package/lib/Bucket.d.ts +38 -4
  16. package/lib/Bucket.d.ts.map +1 -1
  17. package/lib/Bucket.js +190 -37
  18. package/lib/Bucket.js.map +1 -1
  19. package/lib/BucketBinding.d.ts.map +1 -1
  20. package/lib/BucketBinding.js +1 -1
  21. package/lib/BucketBinding.js.map +1 -1
  22. package/lib/Catalog.d.ts.map +1 -1
  23. package/lib/Catalog.js.map +1 -1
  24. package/lib/Certificate.d.ts +25 -1
  25. package/lib/Certificate.d.ts.map +1 -1
  26. package/lib/Certificate.js +22 -4
  27. package/lib/Certificate.js.map +1 -1
  28. package/lib/Checkpoint.d.ts.map +1 -1
  29. package/lib/Checkpoint.js.map +1 -1
  30. package/lib/CheckpointHttp.d.ts.map +1 -1
  31. package/lib/CheckpointHttp.js.map +1 -1
  32. package/lib/ConnectPostgres.d.ts +1 -1
  33. package/lib/ConnectPostgres.d.ts.map +1 -1
  34. package/lib/ConnectPostgres.js.map +1 -1
  35. package/lib/ConnectPostgresHttp.d.ts.map +1 -1
  36. package/lib/ConnectPostgresHttp.js +1 -1
  37. package/lib/ConnectPostgresHttp.js.map +1 -1
  38. package/lib/Contributions.d.ts +1 -1
  39. package/lib/Contributions.d.ts.map +1 -1
  40. package/lib/Contributions.js.map +1 -1
  41. package/lib/Credentials.d.ts +5 -4
  42. package/lib/Credentials.d.ts.map +1 -1
  43. package/lib/Credentials.js +18 -18
  44. package/lib/Credentials.js.map +1 -1
  45. package/lib/Decrypt.d.ts.map +1 -1
  46. package/lib/Decrypt.js.map +1 -1
  47. package/lib/DecryptHttp.d.ts.map +1 -1
  48. package/lib/DecryptHttp.js.map +1 -1
  49. package/lib/DeleteObject.d.ts.map +1 -1
  50. package/lib/DeleteObject.js.map +1 -1
  51. package/lib/DeleteObjectHttp.d.ts.map +1 -1
  52. package/lib/DeleteObjectHttp.js.map +1 -1
  53. package/lib/Deployment.d.ts.map +1 -1
  54. package/lib/Deployment.js.map +1 -1
  55. package/lib/DeploymentImages.d.ts.map +1 -1
  56. package/lib/DeploymentImages.js +1 -1
  57. package/lib/DeploymentImages.js.map +1 -1
  58. package/lib/DeploymentState.d.ts.map +1 -1
  59. package/lib/DeploymentState.js.map +1 -1
  60. package/lib/Encrypt.d.ts.map +1 -1
  61. package/lib/Encrypt.js.map +1 -1
  62. package/lib/EncryptHttp.d.ts.map +1 -1
  63. package/lib/EncryptHttp.js.map +1 -1
  64. package/lib/Environment.d.ts.map +1 -1
  65. package/lib/Environment.js.map +1 -1
  66. package/lib/Errors.d.ts +1 -1
  67. package/lib/Errors.d.ts.map +1 -1
  68. package/lib/Errors.js.map +1 -1
  69. package/lib/Exec.d.ts.map +1 -1
  70. package/lib/Exec.js.map +1 -1
  71. package/lib/ExecHttp.d.ts.map +1 -1
  72. package/lib/ExecHttp.js.map +1 -1
  73. package/lib/GetObject.d.ts.map +1 -1
  74. package/lib/GetObject.js.map +1 -1
  75. package/lib/GetObjectHttp.d.ts.map +1 -1
  76. package/lib/GetObjectHttp.js.map +1 -1
  77. package/lib/GetSecret.d.ts.map +1 -1
  78. package/lib/GetSecret.js.map +1 -1
  79. package/lib/GetSecretHttp.d.ts.map +1 -1
  80. package/lib/GetSecretHttp.js.map +1 -1
  81. package/lib/HeadObject.d.ts.map +1 -1
  82. package/lib/HeadObject.js.map +1 -1
  83. package/lib/HeadObjectHttp.d.ts.map +1 -1
  84. package/lib/HeadObjectHttp.js.map +1 -1
  85. package/lib/IpAssignment.d.ts +24 -1
  86. package/lib/IpAssignment.d.ts.map +1 -1
  87. package/lib/IpAssignment.js +21 -4
  88. package/lib/IpAssignment.js.map +1 -1
  89. package/lib/ListObjectsV2.d.ts.map +1 -1
  90. package/lib/ListObjectsV2.js.map +1 -1
  91. package/lib/ListObjectsV2Http.d.ts.map +1 -1
  92. package/lib/ListObjectsV2Http.js.map +1 -1
  93. package/lib/ListSecrets.d.ts.map +1 -1
  94. package/lib/ListSecrets.js.map +1 -1
  95. package/lib/ListSecretsHttp.d.ts.map +1 -1
  96. package/lib/ListSecretsHttp.js.map +1 -1
  97. package/lib/Machine.d.ts +27 -2
  98. package/lib/Machine.d.ts.map +1 -1
  99. package/lib/Machine.js +18 -3
  100. package/lib/Machine.js.map +1 -1
  101. package/lib/MachineContainers.d.ts.map +1 -1
  102. package/lib/MachineContainers.js.map +1 -1
  103. package/lib/Metadata.d.ts.map +1 -1
  104. package/lib/Metadata.js.map +1 -1
  105. package/lib/MountVolume.d.ts +7 -2
  106. package/lib/MountVolume.d.ts.map +1 -1
  107. package/lib/MountVolume.js.map +1 -1
  108. package/lib/Postgres.d.ts +34 -2
  109. package/lib/Postgres.d.ts.map +1 -1
  110. package/lib/Postgres.js +26 -6
  111. package/lib/Postgres.js.map +1 -1
  112. package/lib/PostgresMigrations.d.ts +7 -22
  113. package/lib/PostgresMigrations.d.ts.map +1 -1
  114. package/lib/PostgresMigrations.js +37 -89
  115. package/lib/PostgresMigrations.js.map +1 -1
  116. package/lib/Providers.d.ts +1 -1
  117. package/lib/Providers.d.ts.map +1 -1
  118. package/lib/Providers.js.map +1 -1
  119. package/lib/PutObject.d.ts.map +1 -1
  120. package/lib/PutObject.js.map +1 -1
  121. package/lib/PutObjectHttp.d.ts.map +1 -1
  122. package/lib/PutObjectHttp.js.map +1 -1
  123. package/lib/ReadRedis.d.ts.map +1 -1
  124. package/lib/ReadRedis.js.map +1 -1
  125. package/lib/ReadRedisHttp.d.ts.map +1 -1
  126. package/lib/ReadRedisHttp.js.map +1 -1
  127. package/lib/ReadWriteRedis.d.ts.map +1 -1
  128. package/lib/ReadWriteRedis.js.map +1 -1
  129. package/lib/ReadWriteRedisHttp.d.ts.map +1 -1
  130. package/lib/ReadWriteRedisHttp.js.map +1 -1
  131. package/lib/Redis.d.ts +23 -3
  132. package/lib/Redis.d.ts.map +1 -1
  133. package/lib/Redis.js +37 -6
  134. package/lib/Redis.js.map +1 -1
  135. package/lib/RedisBinding.d.ts.map +1 -1
  136. package/lib/RedisBinding.js +1 -1
  137. package/lib/RedisBinding.js.map +1 -1
  138. package/lib/RedisHttp.d.ts +1 -1
  139. package/lib/RedisHttp.d.ts.map +1 -1
  140. package/lib/RedisHttp.js +4 -1
  141. package/lib/RedisHttp.js.map +1 -1
  142. package/lib/Region.d.ts.map +1 -1
  143. package/lib/Region.js.map +1 -1
  144. package/lib/Secret.d.ts +23 -2
  145. package/lib/Secret.d.ts.map +1 -1
  146. package/lib/Secret.js +17 -2
  147. package/lib/Secret.js.map +1 -1
  148. package/lib/SecretHttp.d.ts.map +1 -1
  149. package/lib/SecretHttp.js.map +1 -1
  150. package/lib/SecretKey.d.ts +23 -2
  151. package/lib/SecretKey.d.ts.map +1 -1
  152. package/lib/SecretKey.js +17 -2
  153. package/lib/SecretKey.js.map +1 -1
  154. package/lib/SecretKeyHttp.d.ts.map +1 -1
  155. package/lib/SecretKeyHttp.js.map +1 -1
  156. package/lib/Service.d.ts +104 -34
  157. package/lib/Service.d.ts.map +1 -1
  158. package/lib/Service.js +301 -54
  159. package/lib/Service.js.map +1 -1
  160. package/lib/Sign.d.ts.map +1 -1
  161. package/lib/Sign.js.map +1 -1
  162. package/lib/SignHttp.d.ts.map +1 -1
  163. package/lib/SignHttp.js.map +1 -1
  164. package/lib/Sprite.d.ts +24 -5
  165. package/lib/Sprite.d.ts.map +1 -1
  166. package/lib/Sprite.js +22 -5
  167. package/lib/Sprite.js.map +1 -1
  168. package/lib/SpriteHttp.d.ts.map +1 -1
  169. package/lib/SpriteHttp.js.map +1 -1
  170. package/lib/Verify.d.ts.map +1 -1
  171. package/lib/Verify.js.map +1 -1
  172. package/lib/VerifyHttp.d.ts.map +1 -1
  173. package/lib/VerifyHttp.js.map +1 -1
  174. package/lib/Volume.d.ts +4 -4
  175. package/lib/Volume.d.ts.map +1 -1
  176. package/lib/Volume.js +21 -5
  177. package/lib/Volume.js.map +1 -1
  178. package/lib/VolumeSnapshot.d.ts +32 -1
  179. package/lib/VolumeSnapshot.d.ts.map +1 -1
  180. package/lib/VolumeSnapshot.js +24 -1
  181. package/lib/VolumeSnapshot.js.map +1 -1
  182. package/lib/Website/AssetDeployment.d.ts.map +1 -1
  183. package/lib/Website/AssetDeployment.js +9 -9
  184. package/lib/Website/AssetDeployment.js.map +1 -1
  185. package/lib/Website/Astro.d.ts +8 -6
  186. package/lib/Website/Astro.d.ts.map +1 -1
  187. package/lib/Website/Astro.js +12 -13
  188. package/lib/Website/Astro.js.map +1 -1
  189. package/lib/Website/Foldkit.d.ts.map +1 -1
  190. package/lib/Website/Foldkit.js.map +1 -1
  191. package/lib/Website/FrameworkSite.d.ts +39 -2
  192. package/lib/Website/FrameworkSite.d.ts.map +1 -1
  193. package/lib/Website/FrameworkSite.js +46 -3
  194. package/lib/Website/FrameworkSite.js.map +1 -1
  195. package/lib/Website/Nextjs.d.ts.map +1 -1
  196. package/lib/Website/Nextjs.js.map +1 -1
  197. package/lib/Website/Nuxt.d.ts.map +1 -1
  198. package/lib/Website/Nuxt.js.map +1 -1
  199. package/lib/Website/Octane.d.ts.map +1 -1
  200. package/lib/Website/Octane.js.map +1 -1
  201. package/lib/Website/ReactRouter.d.ts.map +1 -1
  202. package/lib/Website/ReactRouter.js.map +1 -1
  203. package/lib/Website/SolidStart.d.ts.map +1 -1
  204. package/lib/Website/SolidStart.js.map +1 -1
  205. package/lib/Website/StaticSite.d.ts +10 -3
  206. package/lib/Website/StaticSite.d.ts.map +1 -1
  207. package/lib/Website/StaticSite.js +16 -4
  208. package/lib/Website/StaticSite.js.map +1 -1
  209. package/lib/Website/SvelteKit.d.ts.map +1 -1
  210. package/lib/Website/SvelteKit.js.map +1 -1
  211. package/lib/Website/TanStackStart.d.ts.map +1 -1
  212. package/lib/Website/TanStackStart.js.map +1 -1
  213. package/lib/Website/Vinext.d.ts.map +1 -1
  214. package/lib/Website/Vinext.js.map +1 -1
  215. package/lib/Website/Vite.d.ts +9 -0
  216. package/lib/Website/Vite.d.ts.map +1 -1
  217. package/lib/Website/Vite.js +9 -0
  218. package/lib/Website/Vite.js.map +1 -1
  219. package/lib/Website/Vocs.d.ts.map +1 -1
  220. package/lib/Website/Vocs.js.map +1 -1
  221. package/lib/Website/Waku.d.ts.map +1 -1
  222. package/lib/Website/Waku.js.map +1 -1
  223. package/lib/Website/index.d.ts.map +1 -1
  224. package/lib/Website/index.js.map +1 -1
  225. package/lib/WriteCertificates.d.ts.map +1 -1
  226. package/lib/WriteCertificates.js.map +1 -1
  227. package/lib/WriteCertificatesHttp.d.ts.map +1 -1
  228. package/lib/WriteCertificatesHttp.js +2 -2
  229. package/lib/WriteCertificatesHttp.js.map +1 -1
  230. package/lib/WriteRedis.d.ts.map +1 -1
  231. package/lib/WriteRedis.js.map +1 -1
  232. package/lib/WriteRedisHttp.d.ts.map +1 -1
  233. package/lib/WriteRedisHttp.js.map +1 -1
  234. package/lib/WriteSecret.d.ts.map +1 -1
  235. package/lib/WriteSecret.js.map +1 -1
  236. package/lib/WriteSecretHttp.d.ts.map +1 -1
  237. package/lib/WriteSecretHttp.js.map +1 -1
  238. package/lib/bluegreen.d.ts +5 -4
  239. package/lib/bluegreen.d.ts.map +1 -1
  240. package/lib/bluegreen.js +7 -5
  241. package/lib/bluegreen.js.map +1 -1
  242. package/lib/hosted.d.ts +19 -4
  243. package/lib/hosted.d.ts.map +1 -1
  244. package/lib/hosted.js +101 -11
  245. package/lib/hosted.js.map +1 -1
  246. package/lib/index.d.ts.map +1 -1
  247. package/lib/index.js.map +1 -1
  248. package/lib/internal/Oidc.d.ts +15 -0
  249. package/lib/internal/Oidc.d.ts.map +1 -0
  250. package/lib/internal/Oidc.js +73 -0
  251. package/lib/internal/Oidc.js.map +1 -0
  252. package/lib/internal/RemoteBuilder.d.ts.map +1 -1
  253. package/lib/internal/RemoteBuilder.js +21 -8
  254. package/lib/internal/RemoteBuilder.js.map +1 -1
  255. package/lib/leases.d.ts +6 -2
  256. package/lib/leases.d.ts.map +1 -1
  257. package/lib/leases.js +25 -5
  258. package/lib/leases.js.map +1 -1
  259. package/lib/ports.d.ts.map +1 -1
  260. package/lib/ports.js.map +1 -1
  261. package/lib/replicas.d.ts +39 -27
  262. package/lib/replicas.d.ts.map +1 -1
  263. package/lib/replicas.js +63 -8
  264. package/lib/replicas.js.map +1 -1
  265. package/lib/rpc.d.ts +14 -12
  266. package/lib/rpc.d.ts.map +1 -1
  267. package/lib/rpc.js +38 -40
  268. package/lib/rpc.js.map +1 -1
  269. package/package.json +15 -15
  270. package/src/App.ts +41 -10
  271. package/src/BindService.ts +28 -36
  272. package/src/Bootstrap.ts +2 -0
  273. package/src/Bucket.ts +278 -45
  274. package/src/BucketBinding.ts +1 -1
  275. package/src/Certificate.ts +36 -5
  276. package/src/ConnectPostgres.ts +1 -1
  277. package/src/ConnectPostgresHttp.ts +1 -1
  278. package/src/Credentials.ts +18 -41
  279. package/src/DeploymentImages.ts +1 -1
  280. package/src/Errors.ts +1 -1
  281. package/src/IpAssignment.ts +35 -5
  282. package/src/Machine.ts +39 -4
  283. package/src/MountVolume.ts +5 -2
  284. package/src/Postgres.ts +50 -8
  285. package/src/PostgresMigrations.ts +39 -99
  286. package/src/Redis.ts +54 -9
  287. package/src/RedisBinding.ts +1 -1
  288. package/src/RedisHttp.ts +4 -1
  289. package/src/Secret.ts +32 -4
  290. package/src/SecretKey.ts +32 -4
  291. package/src/Service.ts +441 -88
  292. package/src/Sprite.ts +45 -17
  293. package/src/Volume.ts +30 -6
  294. package/src/VolumeSnapshot.ts +40 -2
  295. package/src/Website/AssetDeployment.ts +13 -15
  296. package/src/Website/Astro.ts +20 -15
  297. package/src/Website/FrameworkSite.ts +92 -6
  298. package/src/Website/StaticSite.ts +27 -7
  299. package/src/Website/Vite.ts +9 -0
  300. package/src/WriteCertificatesHttp.ts +2 -2
  301. package/src/bluegreen.ts +11 -5
  302. package/src/hosted.ts +121 -17
  303. package/src/internal/Oidc.ts +99 -0
  304. package/src/internal/RemoteBuilder.ts +37 -19
  305. package/src/leases.ts +35 -7
  306. package/src/replicas.ts +70 -9
  307. package/src/rpc.ts +37 -40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alchemy.run/fly",
3
- "version": "2.0.0-beta.84",
3
+ "version": "2.0.0-beta.86",
4
4
  "description": "Fly.io apps, machines and Postgres for Alchemy.",
5
5
  "keywords": [
6
6
  "alchemy",
@@ -57,27 +57,27 @@
57
57
  "access": "public"
58
58
  },
59
59
  "dependencies": {
60
- "@alchemy.run/docker": "2.0.0-beta.84",
61
- "@alchemy.run/redis": "2.0.0-beta.84",
62
- "@alchemy.run/sql": "2.0.0-beta.84",
63
- "@distilled.cloud/aws": "1.0.0-rc.17",
64
- "@distilled.cloud/core": "1.0.0-rc.17",
65
- "@distilled.cloud/fly-io": "1.0.0-rc.17",
66
- "rolldown": "1.2.13"
60
+ "@alchemy.run/docker": "2.0.0-beta.86",
61
+ "@alchemy.run/redis": "2.0.0-beta.86",
62
+ "@alchemy.run/sql": "2.0.0-beta.86",
63
+ "@distilled.cloud/aws": "1.0.0-rc.19",
64
+ "@distilled.cloud/core": "1.0.0-rc.19",
65
+ "@distilled.cloud/fly-io": "1.0.0-rc.19",
66
+ "rolldown": "1.2.16"
67
67
  },
68
68
  "devDependencies": {
69
- "@effect/platform-node": "^4.0.5",
69
+ "@effect/platform-node": "^4.1.4",
70
70
  "@types/bun": "1.4.3",
71
71
  "@types/pg": "^8.20.0",
72
- "alchemy": "2.0.0-beta.84",
73
- "effect": "^4.0.5",
72
+ "alchemy": "2.0.0-beta.86",
73
+ "effect": "^4.1.4",
74
74
  "pg": "^8.22.0",
75
- "typescript": "^7.0.2"
75
+ "typescript": "^7.1.0-dev.20261105.1"
76
76
  },
77
77
  "peerDependencies": {
78
- "@effect/platform-node": "^4.0.5",
79
- "alchemy": "2.0.0-beta.84",
80
- "effect": "^4.0.5",
78
+ "@effect/platform-node": "^4.1.4",
79
+ "alchemy": "2.0.0-beta.86",
80
+ "effect": "^4.1.4",
81
81
  "pg": "^8.22.0"
82
82
  },
83
83
  "peerDependenciesMeta": {
package/src/App.ts CHANGED
@@ -82,9 +82,19 @@ export type App = Resource<
82
82
  url: string;
83
83
  },
84
84
  AppBinding,
85
- Providers
85
+ Providers,
86
+ AppLookup
86
87
  >;
87
88
 
89
+ /**
90
+ * Props for {@link App.lookup}: find an App this stack doesn't manage by
91
+ * its name.
92
+ */
93
+ export interface AppLookup {
94
+ /** Fly App name. */
95
+ name: string;
96
+ }
97
+
88
98
  /**
89
99
  * Binding contract accepted by {@link App}. Each {@link Service} placed in
90
100
  * the App (`app` prop) reports the ports it publishes, so the App can
@@ -196,18 +206,32 @@ export interface AppBinding {
196
206
  * export const Site = Fly.App("Site");
197
207
  * ```
198
208
  *
209
+ * ### Looking up an existing App
210
+ * `App.lookup` references an App Alchemy doesn't manage (created with
211
+ * `fly launch` or by another stack). It is read during plan/deploy, never
212
+ * created, updated or deleted, and works anywhere a declared App does.
213
+ *
214
+ * **Example:** Reference an existing App
215
+ * ```typescript
216
+ * const site = Fly.App.lookup({ name: "my-site" });
217
+ * const db = yield* Fly.Secret("DatabaseUrl", {
218
+ * app: site,
219
+ * value: Redacted.make("postgres://…"),
220
+ * });
221
+ * ```
222
+ *
199
223
  * @resource
200
224
  * @product App
201
225
  */
202
226
  export const App = Resource<App>("Fly.App");
203
227
 
204
228
  export class AppNotCreated extends Data.TaggedError("Fly.AppNotCreated")<{
205
- name: string;
229
+ resourceName: string;
206
230
  /** Fly's rejection of the create request, when there was one. */
207
231
  reason?: string;
208
232
  }> {
209
233
  get message() {
210
- return `Fly App ${this.name} was not created${this.reason ? `: ${this.reason}` : ""}`;
234
+ return `Fly App ${this.resourceName} was not created${this.reason ? `: ${this.reason}` : ""}`;
211
235
  }
212
236
  }
213
237
 
@@ -234,9 +258,7 @@ const resolveAppName = (id: string, name: string | undefined, existing?: string)
234
258
  });
235
259
 
236
260
  const getByName = (appName: string) =>
237
- machines
238
- .getApp({ app_name: appName })
239
- .pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
261
+ machines.getApp({ app_name: appName }).pipe(Effect.catchTag("NotFound", () => Effect.undefined));
240
262
 
241
263
  const hasAlchemyMachines = (appName: string) =>
242
264
  machines.listMachines({ app_name: appName }).pipe(
@@ -348,11 +370,11 @@ export const ensureApp = Effect.fn(function* (input: {
348
370
  current = yield* observe;
349
371
  }
350
372
  if (current === undefined) {
351
- return yield* new AppNotCreated({ name: input.name, reason: rejection });
373
+ return yield* new AppNotCreated({ resourceName: input.name, reason: rejection });
352
374
  }
353
375
  }
354
376
  if (current === undefined) {
355
- return yield* new AppNotCreated({ name: input.name });
377
+ return yield* new AppNotCreated({ resourceName: input.name });
356
378
  }
357
379
  return current;
358
380
  });
@@ -387,7 +409,7 @@ export const deleteApp = Effect.fn(function* (appName: string) {
387
409
  );
388
410
  const http = yield* HttpClient.HttpClient;
389
411
  const fetchOptions = yield* Effect.serviceOption(FetchHttpClient.RequestInit);
390
- yield* machines.deleteApp({ app_name: appName }).pipe(
412
+ const accepted = yield* machines.deleteApp({ app_name: appName }).pipe(
391
413
  Retry.none,
392
414
  // Bun can replay DELETE on a reused socket below the SDK retry policy.
393
415
  Effect.provideService(
@@ -400,7 +422,10 @@ export const deleteApp = Effect.fn(function* (appName: string) {
400
422
  redirect: "error",
401
423
  }),
402
424
  Effect.timeout("30 seconds"),
403
- Effect.catchTag("NotFound", () => Effect.void),
425
+ Effect.as(true),
426
+ // Fly's DELETE is authoritative for absence: its GET can keep serving a
427
+ // deleted App as `pending` long after DELETE answers 404.
428
+ Effect.catchTag("NotFound", () => Effect.succeed(false)),
404
429
  Effect.catchTag(
405
430
  [
406
431
  "HttpClientError",
@@ -413,6 +438,7 @@ export const deleteApp = Effect.fn(function* (appName: string) {
413
438
  (error) => Effect.fail(new AppDeletionAmbiguous({ appName, evidence: error._tag })),
414
439
  ),
415
440
  );
441
+ if (!accepted) return;
416
442
  const gone = yield* getByName(appName).pipe(
417
443
  Effect.map((app) => app === undefined),
418
444
  Effect.repeat({ schedule: Schedule.spaced("1 second"), until: (gone) => gone, times: 8 }),
@@ -481,6 +507,11 @@ export const AppProvider = () =>
481
507
  return undefined;
482
508
  }),
483
509
 
510
+ lookup: Effect.fn(function* ({ name }) {
511
+ const found = yield* getByName(name);
512
+ return found === undefined ? undefined : toAttrs(found, name);
513
+ }),
514
+
484
515
  read: Effect.fn(function* ({ id, olds, output }) {
485
516
  const name = yield* resolveAppName(id, olds?.name, output?.appName);
486
517
  const found =
@@ -1,6 +1,6 @@
1
1
  import * as Binding from "alchemy/Binding";
2
2
  import type { Resource } from "alchemy/Resource";
3
- import { makeFetchRpcStub, RPC_PATH_PREFIX, type Rpc } from "alchemy/Rpc";
3
+ import { makeFetchRpcStub, type Rpc } from "alchemy/Rpc";
4
4
  import { CurrentRuntimeContext, type RuntimeContext, sanitizeKey } from "alchemy/RuntimeContext";
5
5
  import { isYieldableEffectLike } from "alchemy/Util/effect";
6
6
  import * as Data from "effect/Data";
@@ -9,9 +9,7 @@ import * as HttpClient from "effect/http/HttpClient";
9
9
  import type * as HttpClientError from "effect/http/HttpClientError";
10
10
  import * as HttpClientRequest from "effect/http/HttpClientRequest";
11
11
  import type * as HttpClientResponse from "effect/http/HttpClientResponse";
12
- import * as Redacted from "effect/Redacted";
13
12
  import type { BoundTarget, ServiceBinding } from "./MountVolume.ts";
14
- import { RPC_TOKEN_HEADER } from "./rpc.ts";
15
13
  import type { Service } from "./Service.ts";
16
14
 
17
15
  /** The deployed caller has no address for the bound Service. */
@@ -75,12 +73,13 @@ const logicalIdOf = (target: unknown): string => {
75
73
  export const boundTargetEnvKeys = (id: string) => ({
76
74
  appName: sanitizeKey(`FLY_BIND_${id}_APP`),
77
75
  url: sanitizeKey(`FLY_BIND_${id}_URL`),
78
- token: sanitizeKey(`FLY_BIND_${id}_TOKEN`),
79
76
  });
80
77
 
81
78
  /**
82
79
  * Record the binding on the caller and transport the target's private
83
- * address and caller token as Outputs. Returns runtime accessors for them.
80
+ * address as Outputs. For {@link bindService}, also record the caller's
81
+ * App on the target, which serves its methods only to the Apps recorded
82
+ * there. Returns runtime accessors for the address.
84
83
  */
85
84
  const bindTarget = Effect.fn(function* <Shape, Req>(
86
85
  target: Target<Shape> | Effect.Effect<Target<Shape>, never, Req>,
@@ -105,17 +104,27 @@ const bindTarget = Effect.fn(function* <Shape, Req>(
105
104
  appName: service.appName,
106
105
  network: service.network,
107
106
  privateUrl: service.privateUrl,
108
- rpcToken: service.rpcToken,
109
107
  port,
110
108
  endpoints: service.endpoints,
111
109
  } as unknown as BoundTarget,
112
110
  });
111
+ if (port === undefined) {
112
+ // Fly signs each request's calling App (`Fly-Src`), so the target
113
+ // authorizes callers by App: no key to hand out.
114
+ yield* (
115
+ service as unknown as {
116
+ bind: (
117
+ label: TemplateStringsArray,
118
+ ...args: unknown[]
119
+ ) => (data: ServiceBinding) => Effect.Effect<void>;
120
+ }
121
+ ).bind`Caller(${host})`({ caller: { appName: host.appName as unknown as string } });
122
+ }
113
123
  }
114
124
  }
115
125
  // Captured at bind time: the host's runtime context reads the values
116
126
  // transported onto the Machine.
117
- const read = (key: string) =>
118
- ctx === undefined ? Effect.succeed(undefined) : ctx.get<unknown>(key);
127
+ const read = (key: string) => (ctx === undefined ? Effect.undefined : ctx.get<unknown>(key));
119
128
  const required = (key: string) =>
120
129
  read(key).pipe(
121
130
  Effect.flatMap((value) =>
@@ -127,15 +136,6 @@ const bindTarget = Effect.fn(function* <Shape, Req>(
127
136
  return {
128
137
  appName: required(keys.appName),
129
138
  url: required(keys.url),
130
- token: read(keys.token).pipe(
131
- Effect.map((value) =>
132
- Redacted.isRedacted(value)
133
- ? String(Redacted.value(value))
134
- : typeof value === "string"
135
- ? value
136
- : "",
137
- ),
138
- ),
139
139
  };
140
140
  });
141
141
 
@@ -151,12 +151,13 @@ const withBase = (base: string, url: string) => {
151
151
  * `fetch` and `run`) and forwards `fetch` requests, over Fly's private
152
152
  * network.
153
153
  *
154
- * Binding makes the caller deploy after the Service and hands it the
155
- * Service's private address and caller token. Only callers that bind a
156
- * Service receive its token, so other Services on the same network cannot
157
- * call its methods. Every call must also carry Fly's signed `Fly-Src`
158
- * header from the same organization, so the public internet cannot call
159
- * them. Calls are plain HTTP inside Fly's WireGuard-encrypted network.
154
+ * Binding makes the caller deploy after the Service, hands it the
155
+ * Service's private address, and records the caller's App on the Service.
156
+ * Fly's proxy signs every call with the calling App (`Fly-Src`), and the
157
+ * Service answers methods only for the Apps recorded on it, so neither
158
+ * other Services on the network nor the public internet can call them,
159
+ * and no key is involved. Calls are plain HTTP inside Fly's
160
+ * WireGuard-encrypted network.
160
161
  *
161
162
  * ### Call a private Service
162
163
  * **Example:** Methods on the target
@@ -251,24 +252,15 @@ export const bindService = <Shape, Req = never>(
251
252
  Effect.gen(function* () {
252
253
  const http = yield* HttpClient.HttpClient;
253
254
  const bound = yield* bindTarget(target, undefined);
254
- const send = (request: HttpClientRequest.HttpClientRequest, isRpc: boolean) =>
255
+ const send = (request: HttpClientRequest.HttpClientRequest) =>
255
256
  Effect.gen(function* () {
256
257
  const base = yield* bound.url;
257
- let next = HttpClientRequest.setUrl(request, withBase(base, request.url));
258
- if (isRpc) {
259
- next = HttpClientRequest.setHeader(next, RPC_TOKEN_HEADER, yield* bound.token);
260
- }
261
- return yield* http.execute(next);
258
+ return yield* http.execute(HttpClientRequest.setUrl(request, withBase(base, request.url)));
262
259
  });
263
260
  return makeFetchRpcStub<ServiceClient<Shape>>({
264
261
  fetch: (request) =>
265
- send(request, request.url.includes(RPC_PATH_PREFIX)) as Effect.Effect<
266
- HttpClientResponse.HttpClientResponse,
267
- unknown
268
- >,
269
- base: {
270
- fetch: (request: HttpClientRequest.HttpClientRequest) => send(request, false),
271
- },
262
+ send(request) as Effect.Effect<HttpClientResponse.HttpClientResponse, unknown>,
263
+ base: { fetch: send },
272
264
  });
273
265
  });
274
266
 
package/src/Bootstrap.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  } from "alchemy/Runtime/Bootstrap";
15
15
  import { ManagedHttpShutdown } from "alchemy/Runtime/ManagedHttpShutdown";
16
16
  import * as ConfigProvider from "effect/ConfigProvider";
17
+ import * as SecureRandom from "effect/crypto/SecureRandom";
17
18
  import * as Effect from "effect/Effect";
18
19
  import * as FetchHttpClient from "effect/http/FetchHttpClient";
19
20
  import * as Layer from "effect/Layer";
@@ -31,6 +32,7 @@ export const bootstrap = (entrypoint: unknown): Promise<void> => {
31
32
  const platform = Layer.mergeAll(
32
33
  NodeServices.layer,
33
34
  FetchHttpClient.layer,
35
+ SecureRandom.layerWebCrypto,
34
36
  Logger.layer([Logger.consolePretty()]),
35
37
  );
36
38