@alchemy.run/archil 0.0.0 → 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 (184) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +57 -4
  3. package/lib/AWS/S3Disk.d.ts +68 -0
  4. package/lib/AWS/S3Disk.d.ts.map +1 -0
  5. package/lib/AWS/S3Disk.js +100 -0
  6. package/lib/AWS/S3Disk.js.map +1 -0
  7. package/lib/AWS/index.d.ts +2 -0
  8. package/lib/AWS/index.d.ts.map +1 -0
  9. package/lib/AWS/index.js +2 -0
  10. package/lib/AWS/index.js.map +1 -0
  11. package/lib/ApiToken.d.ts +63 -0
  12. package/lib/ApiToken.d.ts.map +1 -0
  13. package/lib/ApiToken.js +121 -0
  14. package/lib/ApiToken.js.map +1 -0
  15. package/lib/ArchilBindings.d.ts +65 -0
  16. package/lib/ArchilBindings.d.ts.map +1 -0
  17. package/lib/ArchilBindings.js +128 -0
  18. package/lib/ArchilBindings.js.map +1 -0
  19. package/lib/AuthProvider.d.ts +40 -0
  20. package/lib/AuthProvider.d.ts.map +1 -0
  21. package/lib/AuthProvider.js +87 -0
  22. package/lib/AuthProvider.js.map +1 -0
  23. package/lib/Bootstrap.d.ts +8 -0
  24. package/lib/Bootstrap.d.ts.map +1 -0
  25. package/lib/Bootstrap.js +27 -0
  26. package/lib/Bootstrap.js.map +1 -0
  27. package/lib/Branch.d.ts +101 -0
  28. package/lib/Branch.d.ts.map +1 -0
  29. package/lib/Branch.js +117 -0
  30. package/lib/Branch.js.map +1 -0
  31. package/lib/BranchDisk.d.ts +42 -0
  32. package/lib/BranchDisk.d.ts.map +1 -0
  33. package/lib/BranchDisk.js +14 -0
  34. package/lib/BranchDisk.js.map +1 -0
  35. package/lib/Checkpoint.d.ts +78 -0
  36. package/lib/Checkpoint.d.ts.map +1 -0
  37. package/lib/Checkpoint.js +95 -0
  38. package/lib/Checkpoint.js.map +1 -0
  39. package/lib/Clients.d.ts +369 -0
  40. package/lib/Clients.d.ts.map +1 -0
  41. package/lib/Clients.js +334 -0
  42. package/lib/Clients.js.map +1 -0
  43. package/lib/ConnectSandbox.d.ts +69 -0
  44. package/lib/ConnectSandbox.d.ts.map +1 -0
  45. package/lib/ConnectSandbox.js +21 -0
  46. package/lib/ConnectSandbox.js.map +1 -0
  47. package/lib/Contributions.d.ts +7 -0
  48. package/lib/Contributions.d.ts.map +1 -0
  49. package/lib/Contributions.js +6 -0
  50. package/lib/Contributions.js.map +1 -0
  51. package/lib/CreateDisk.d.ts +90 -0
  52. package/lib/CreateDisk.d.ts.map +1 -0
  53. package/lib/CreateDisk.js +47 -0
  54. package/lib/CreateDisk.js.map +1 -0
  55. package/lib/CreateImage.d.ts +42 -0
  56. package/lib/CreateImage.d.ts.map +1 -0
  57. package/lib/CreateImage.js +19 -0
  58. package/lib/CreateImage.js.map +1 -0
  59. package/lib/CreateSandbox.d.ts +104 -0
  60. package/lib/CreateSandbox.d.ts.map +1 -0
  61. package/lib/CreateSandbox.js +98 -0
  62. package/lib/CreateSandbox.js.map +1 -0
  63. package/lib/Credentials.d.ts +44 -0
  64. package/lib/Credentials.d.ts.map +1 -0
  65. package/lib/Credentials.js +57 -0
  66. package/lib/Credentials.js.map +1 -0
  67. package/lib/Disk.d.ts +283 -0
  68. package/lib/Disk.d.ts.map +1 -0
  69. package/lib/Disk.js +294 -0
  70. package/lib/Disk.js.map +1 -0
  71. package/lib/DiskObjectsHttp.d.ts +20 -0
  72. package/lib/DiskObjectsHttp.d.ts.map +1 -0
  73. package/lib/DiskObjectsHttp.js +51 -0
  74. package/lib/DiskObjectsHttp.js.map +1 -0
  75. package/lib/DiskUser.d.ts +189 -0
  76. package/lib/DiskUser.d.ts.map +1 -0
  77. package/lib/DiskUser.js +243 -0
  78. package/lib/DiskUser.js.map +1 -0
  79. package/lib/ExecDisk.d.ts +57 -0
  80. package/lib/ExecDisk.d.ts.map +1 -0
  81. package/lib/ExecDisk.js +3 -0
  82. package/lib/ExecDisk.js.map +1 -0
  83. package/lib/ExecDiskHttp.d.ts +5 -0
  84. package/lib/ExecDiskHttp.d.ts.map +1 -0
  85. package/lib/ExecDiskHttp.js +18 -0
  86. package/lib/ExecDiskHttp.js.map +1 -0
  87. package/lib/ExecDisks.d.ts +54 -0
  88. package/lib/ExecDisks.d.ts.map +1 -0
  89. package/lib/ExecDisks.js +37 -0
  90. package/lib/ExecDisks.js.map +1 -0
  91. package/lib/Image.d.ts +188 -0
  92. package/lib/Image.d.ts.map +1 -0
  93. package/lib/Image.js +191 -0
  94. package/lib/Image.js.map +1 -0
  95. package/lib/InferEnv.d.ts +26 -0
  96. package/lib/InferEnv.d.ts.map +1 -0
  97. package/lib/InferEnv.js +1 -0
  98. package/lib/InferEnv.js.map +1 -0
  99. package/lib/MountDisk.d.ts +190 -0
  100. package/lib/MountDisk.d.ts.map +1 -0
  101. package/lib/MountDisk.js +227 -0
  102. package/lib/MountDisk.js.map +1 -0
  103. package/lib/Providers.d.ts +25 -0
  104. package/lib/Providers.d.ts.map +1 -0
  105. package/lib/Providers.js +48 -0
  106. package/lib/Providers.js.map +1 -0
  107. package/lib/ReadDisk.d.ts +55 -0
  108. package/lib/ReadDisk.d.ts.map +1 -0
  109. package/lib/ReadDisk.js +3 -0
  110. package/lib/ReadDisk.js.map +1 -0
  111. package/lib/ReadWriteDisk.d.ts +26 -0
  112. package/lib/ReadWriteDisk.d.ts.map +1 -0
  113. package/lib/ReadWriteDisk.js +3 -0
  114. package/lib/ReadWriteDisk.js.map +1 -0
  115. package/lib/Sandbox.d.ts +507 -0
  116. package/lib/Sandbox.d.ts.map +1 -0
  117. package/lib/Sandbox.js +729 -0
  118. package/lib/Sandbox.js.map +1 -0
  119. package/lib/SandboxOptions.d.ts +185 -0
  120. package/lib/SandboxOptions.d.ts.map +1 -0
  121. package/lib/SandboxOptions.js +102 -0
  122. package/lib/SandboxOptions.js.map +1 -0
  123. package/lib/SandboxPortToken.d.ts +64 -0
  124. package/lib/SandboxPortToken.d.ts.map +1 -0
  125. package/lib/SandboxPortToken.js +77 -0
  126. package/lib/SandboxPortToken.js.map +1 -0
  127. package/lib/WriteDisk.d.ts +37 -0
  128. package/lib/WriteDisk.d.ts.map +1 -0
  129. package/lib/WriteDisk.js +3 -0
  130. package/lib/WriteDisk.js.map +1 -0
  131. package/lib/index.d.ts +29 -0
  132. package/lib/index.d.ts.map +1 -0
  133. package/lib/index.js +28 -0
  134. package/lib/index.js.map +1 -0
  135. package/lib/internal/DeployerKey.d.ts +21 -0
  136. package/lib/internal/DeployerKey.d.ts.map +1 -0
  137. package/lib/internal/DeployerKey.js +34 -0
  138. package/lib/internal/DeployerKey.js.map +1 -0
  139. package/lib/internal/archil.d.ts +87 -0
  140. package/lib/internal/archil.d.ts.map +1 -0
  141. package/lib/internal/archil.js +154 -0
  142. package/lib/internal/archil.js.map +1 -0
  143. package/lib/internal/hosted.d.ts +90 -0
  144. package/lib/internal/hosted.d.ts.map +1 -0
  145. package/lib/internal/hosted.js +291 -0
  146. package/lib/internal/hosted.js.map +1 -0
  147. package/package.json +79 -3
  148. package/src/AWS/S3Disk.ts +125 -0
  149. package/src/AWS/index.ts +1 -0
  150. package/src/ApiToken.ts +168 -0
  151. package/src/ArchilBindings.ts +179 -0
  152. package/src/AuthProvider.ts +122 -0
  153. package/src/Bootstrap.ts +54 -0
  154. package/src/Branch.ts +199 -0
  155. package/src/BranchDisk.ts +57 -0
  156. package/src/Checkpoint.ts +145 -0
  157. package/src/Clients.ts +954 -0
  158. package/src/ConnectSandbox.ts +91 -0
  159. package/src/Contributions.ts +9 -0
  160. package/src/CreateDisk.ts +165 -0
  161. package/src/CreateImage.ts +73 -0
  162. package/src/CreateSandbox.ts +258 -0
  163. package/src/Credentials.ts +101 -0
  164. package/src/Disk.ts +468 -0
  165. package/src/DiskObjectsHttp.ts +64 -0
  166. package/src/DiskUser.ts +369 -0
  167. package/src/ExecDisk.ts +62 -0
  168. package/src/ExecDiskHttp.ts +25 -0
  169. package/src/ExecDisks.ts +100 -0
  170. package/src/Image.ts +316 -0
  171. package/src/InferEnv.ts +27 -0
  172. package/src/MountDisk.ts +466 -0
  173. package/src/Providers.ts +75 -0
  174. package/src/ReadDisk.ts +61 -0
  175. package/src/ReadWriteDisk.ts +31 -0
  176. package/src/Sandbox.ts +1064 -0
  177. package/src/SandboxOptions.ts +230 -0
  178. package/src/SandboxPortToken.ts +125 -0
  179. package/src/WriteDisk.ts +42 -0
  180. package/src/globals.d.ts +2 -0
  181. package/src/index.ts +59 -0
  182. package/src/internal/DeployerKey.ts +63 -0
  183. package/src/internal/archil.ts +273 -0
  184. package/src/internal/hosted.ts +402 -0
@@ -0,0 +1,51 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Layer from "effect/Layer";
3
+ import { DiskKeyAccess } from "./ArchilBindings.js";
4
+ import { makeReadDiskClient, makeWriteDiskClient, presignedShare } from "./Clients.js";
5
+ import { ReadDisk } from "./ReadDisk.js";
6
+ import { ReadWriteDisk } from "./ReadWriteDisk.js";
7
+ import { WriteDisk } from "./WriteDisk.js";
8
+ const diskRef = Effect.fn(function* (disk, options) {
9
+ const diskId = yield* disk.diskId;
10
+ return Effect.map(diskId, (id) => ({ disk: id, branch: options?.branch }));
11
+ });
12
+ /**
13
+ * {@link ReadDisk} over Archil's S3-compatible API, usable from any host.
14
+ * The host gets a read-only S3 user on the disk.
15
+ */
16
+ export const ReadDiskHttp = Layer.effect(ReadDisk, Effect.gen(function* () {
17
+ const keys = yield* DiskKeyAccess;
18
+ return Effect.fn(function* (disk, options) {
19
+ const ref = yield* diskRef(disk, options);
20
+ const run = yield* keys(disk, "read");
21
+ return makeReadDiskClient(ref, run, presignedShare(run));
22
+ });
23
+ }));
24
+ /**
25
+ * {@link WriteDisk} over Archil's S3-compatible API, usable from any host.
26
+ * The host gets a read-write S3 user on the disk.
27
+ */
28
+ export const WriteDiskHttp = Layer.effect(WriteDisk, Effect.gen(function* () {
29
+ const keys = yield* DiskKeyAccess;
30
+ return Effect.fn(function* (disk, options) {
31
+ const ref = yield* diskRef(disk, options);
32
+ const run = yield* keys(disk, "write");
33
+ return makeWriteDiskClient(ref, run);
34
+ });
35
+ }));
36
+ /**
37
+ * {@link ReadWriteDisk} over Archil's S3-compatible API, usable from any
38
+ * host. The host gets a read-write S3 user on the disk.
39
+ */
40
+ export const ReadWriteDiskHttp = Layer.effect(ReadWriteDisk, Effect.gen(function* () {
41
+ const keys = yield* DiskKeyAccess;
42
+ return Effect.fn(function* (disk, options) {
43
+ const ref = yield* diskRef(disk, options);
44
+ const run = yield* keys(disk, "write");
45
+ return {
46
+ ...makeReadDiskClient(ref, run, presignedShare(run)),
47
+ ...makeWriteDiskClient(ref, run),
48
+ };
49
+ });
50
+ }));
51
+ //# sourceMappingURL=DiskObjectsHttp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiskObjectsHttp.js","sources":["../src/DiskObjectsHttp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,189 @@
1
+ import * as archil from "@distilled.cloud/archil";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Redacted from "effect/Redacted";
6
+ import type { Providers } from "./Providers.ts";
7
+ declare const DiskUserUnexpectedResponse_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
8
+ readonly _tag: "Archil.DiskUserUnexpectedResponse";
9
+ } & Readonly<A>;
10
+ export declare class DiskUserUnexpectedResponse extends DiskUserUnexpectedResponse_base<{
11
+ readonly message: string;
12
+ }> {
13
+ }
14
+ export interface DiskUserProps {
15
+ /** Id of the disk the user can mount (e.g. `disk.diskId`). Changing it replaces the user. */
16
+ disk: string;
17
+ /**
18
+ * Name shown in the console. If omitted, a unique name is generated from
19
+ * the stack, stage, and logical ID. Changing it replaces the user.
20
+ */
21
+ nickname?: string;
22
+ /**
23
+ * An AWS IAM role or user ARN that mounts with its own AWS identity
24
+ * instead of a token, e.g. an ECS task role. Changing it replaces the user.
25
+ */
26
+ principal?: string;
27
+ /**
28
+ * `token` mounts with a disk token; `s3` gets an access key pair for the
29
+ * disk's S3-compatible API instead. Ignored when `principal` is set (an
30
+ * `awssts` user). Changing it replaces the user.
31
+ * @default "token"
32
+ */
33
+ type?: "token" | "s3";
34
+ /**
35
+ * Mounts made with this user reject writes (`EROFS`); an `s3` user can
36
+ * only `GET` and `HEAD`. Changing it replaces the user.
37
+ * @default false
38
+ */
39
+ readOnly?: boolean;
40
+ /**
41
+ * When the user stops working, as an RFC 3339 timestamp in the future
42
+ * (at most 365 days away). Requests signed with an expired `s3` key,
43
+ * presigned URLs included, are rejected. Changing it replaces the user.
44
+ */
45
+ expiresAt?: string;
46
+ /**
47
+ * The user works for one mount only; later mounts with it are rejected.
48
+ * Not available for `s3` users. Changing it replaces the user.
49
+ * @default false
50
+ */
51
+ oneUse?: boolean;
52
+ }
53
+ export interface DiskUserAttributes {
54
+ /** Id of the disk. */
55
+ diskId: string;
56
+ /** `token`, `s3` for an access key pair, or `awssts` for an IAM principal. */
57
+ type: "token" | "awssts" | "s3";
58
+ /** Archil's identifier for the user, used to revoke it. */
59
+ identifier: string;
60
+ /** Name shown in the console. */
61
+ nickname: string;
62
+ /** The IAM ARN, for an `awssts` user. */
63
+ principal: string | undefined;
64
+ /**
65
+ * The disk token, for a `token` user. Pass it to `archil mount` as
66
+ * `ARCHIL_MOUNT_TOKEN`. It works only for this disk.
67
+ */
68
+ token: Redacted.Redacted<string> | undefined;
69
+ /** The S3 access key id, for an `s3` user. */
70
+ accessKeyId: string | undefined;
71
+ /**
72
+ * The S3 secret access key, for an `s3` user. Sign requests to the disk's
73
+ * S3-compatible API with it; it works only for this disk.
74
+ */
75
+ secretAccessKey: Redacted.Redacted<string> | undefined;
76
+ /** Whether the user is read-only. */
77
+ readOnly: boolean;
78
+ /** When the user expires, if it does. */
79
+ expiresAt: string | undefined;
80
+ /** Whether the user works for one mount only. */
81
+ oneUse: boolean;
82
+ }
83
+ export type DiskUser = Resource<"Archil.DiskUser", DiskUserProps, DiskUserAttributes, never, Providers>;
84
+ /**
85
+ * Access to one disk. A token user gets a disk token for `archil mount`; an
86
+ * `s3` user gets an access key pair for the disk's S3-compatible API; an
87
+ * IAM user lets an AWS principal mount with its own identity, so no secret
88
+ * exists at all. Archil checks each one itself, so a host holding a disk
89
+ * user can't reach any other disk. `readOnly`, `expiresAt` and `oneUse`
90
+ * narrow it further.
91
+ *
92
+ * Archil only shows a token or secret key once, when it's created, so
93
+ * Alchemy stores it in state as a `Redacted` value. Destroying the user
94
+ * revokes it. `Archil.MountDisk(disk)` and the object bindings
95
+ * (`Archil.ReadDisk`, `Archil.WriteDisk`, `Archil.ReadWriteDisk`) create
96
+ * one per host for you.
97
+ *
98
+ * :::caution
99
+ * Archil can't change a user, so changing any prop replaces it: the old
100
+ * token or key stops working once the new one exists.
101
+ * :::
102
+ * @see https://docs.archil.com/concepts/sharing-disks
103
+ *
104
+ * ### Creating a Disk User
105
+ * **Example:** A token for one machine
106
+ * ```typescript
107
+ * const user = yield* Archil.DiskUser("Indexer", { disk: dataset.diskId });
108
+ * // ARCHIL_MOUNT_TOKEN=<user.token> archil mount <disk> /mnt/data --region aws-us-east-1
109
+ * ```
110
+ *
111
+ * **Example:** An ECS task role that mounts with its own identity
112
+ * ```typescript
113
+ * const user = yield* Archil.DiskUser("Workers", {
114
+ * disk: dataset.diskId,
115
+ * principal: taskRole.roleArn,
116
+ * });
117
+ * ```
118
+ *
119
+ * **Example:** A read-only token that expires
120
+ * ```typescript
121
+ * const user = yield* Archil.DiskUser("Viewer", {
122
+ * disk: dataset.diskId,
123
+ * readOnly: true,
124
+ * expiresAt: "2027-01-01T00:00:00Z",
125
+ * });
126
+ * ```
127
+ *
128
+ * ### S3 Keys
129
+ * **Example:** A read-only access key pair for one disk
130
+ * ```typescript
131
+ * const reader = yield* Archil.DiskUser("Reader", {
132
+ * disk: dataset.diskId,
133
+ * type: "s3",
134
+ * readOnly: true,
135
+ * });
136
+ * // reader.accessKeyId, reader.secretAccessKey sign requests to
137
+ * // https://s3.green.us-east-1.aws.prod.archil.com/<disk id>/<key>
138
+ * ```
139
+ *
140
+ * @resource
141
+ * @product Disk
142
+ */
143
+ export declare const DiskUser: import("alchemy").ResourceClass<DiskUser>;
144
+ /**
145
+ * The authorized user on a disk with this identifier, nickname or principal.
146
+ *
147
+ * For a few seconds after a user is added, some `getDisk` reads still list
148
+ * the disk without it (removals show at once). So a listed user exists, but
149
+ * a user we created (`match.identifier`) counts as missing only after reads
150
+ * across that window all miss it.
151
+ */
152
+ export declare const findDiskUser: (diskId: string, match: {
153
+ nickname?: string;
154
+ principal?: string;
155
+ identifier?: string;
156
+ }) => Effect.Effect<archil.AuthorizedUser | undefined, archil.GetDiskError, archil.ArchilOpContext>;
157
+ /** What a disk user is created with. */
158
+ export interface DiskUserSpec {
159
+ readonly nickname: string;
160
+ readonly principal?: string;
161
+ readonly type?: "token" | "s3";
162
+ readonly readOnly?: boolean;
163
+ readonly expiresAt?: string;
164
+ readonly oneUse?: boolean;
165
+ }
166
+ /** Add a token, S3, or IAM user to a disk. */
167
+ export declare const addDiskUser: (diskId: string, user: DiskUserSpec) => Effect.Effect<{
168
+ diskId: string;
169
+ type: "awssts" | "s3" | "token";
170
+ identifier: string;
171
+ nickname: string;
172
+ principal: string | undefined;
173
+ token: Redacted.Redacted<string> | undefined;
174
+ accessKeyId: string | undefined;
175
+ secretAccessKey: Redacted.Redacted<string> | undefined;
176
+ readOnly: boolean;
177
+ expiresAt: string | undefined;
178
+ oneUse: boolean;
179
+ }, DiskUserUnexpectedResponse | archil.AddDiskUserError, archil.ArchilOpContext>;
180
+ /** Revoke a disk user. Revoking a missing user (or one on a deleted disk) succeeds. */
181
+ export declare const removeDiskUser: (attrs: {
182
+ diskId: string;
183
+ type: "token" | "awssts" | "s3";
184
+ identifier: string;
185
+ principal?: string;
186
+ }) => Effect.Effect<void, archil.ArchilParseError | archil.BadGateway | import("@distilled.cloud/core/errors").BadRequest | archil.BadRequest | archil.ConfigError | import("@distilled.cloud/core/errors").Conflict | import("@distilled.cloud/core/errors").Forbidden | archil.GatewayTimeout | import("effect/http/HttpClientError").HttpClientError | archil.InternalServerError | import("@distilled.cloud/core/protocol-http").InvalidInput | archil.Locked | import("@distilled.cloud/core/sdk-error").SdkError | archil.ServiceUnavailable | archil.TooManyRequests | archil.Unauthorized | archil.UnknownArchilError | archil.UnprocessableEntity, archil.ArchilOpContext>;
187
+ export declare const DiskUserProvider: () => import("effect/Layer").Layer<Provider.Provider<DiskUser>, never, import("alchemy").Stack | import("alchemy").Stage | archil.ArchilOpContext>;
188
+ export {};
189
+ //# sourceMappingURL=DiskUser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiskUser.d.ts","sources":["../src/DiskUser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,243 @@
1
+ import * as archil from "@distilled.cloud/archil";
2
+ import { isResolved } from "alchemy/Diff";
3
+ import { createPhysicalName } from "alchemy/PhysicalName";
4
+ import * as Provider from "alchemy/Provider";
5
+ import { Resource } from "alchemy/Resource";
6
+ import * as Data from "effect/Data";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Redacted from "effect/Redacted";
9
+ import * as Schedule from "effect/Schedule";
10
+ export class DiskUserUnexpectedResponse extends Data.TaggedError("Archil.DiskUserUnexpectedResponse") {
11
+ }
12
+ /**
13
+ * Access to one disk. A token user gets a disk token for `archil mount`; an
14
+ * `s3` user gets an access key pair for the disk's S3-compatible API; an
15
+ * IAM user lets an AWS principal mount with its own identity, so no secret
16
+ * exists at all. Archil checks each one itself, so a host holding a disk
17
+ * user can't reach any other disk. `readOnly`, `expiresAt` and `oneUse`
18
+ * narrow it further.
19
+ *
20
+ * Archil only shows a token or secret key once, when it's created, so
21
+ * Alchemy stores it in state as a `Redacted` value. Destroying the user
22
+ * revokes it. `Archil.MountDisk(disk)` and the object bindings
23
+ * (`Archil.ReadDisk`, `Archil.WriteDisk`, `Archil.ReadWriteDisk`) create
24
+ * one per host for you.
25
+ *
26
+ * :::caution
27
+ * Archil can't change a user, so changing any prop replaces it: the old
28
+ * token or key stops working once the new one exists.
29
+ * :::
30
+ * @see https://docs.archil.com/concepts/sharing-disks
31
+ *
32
+ * ### Creating a Disk User
33
+ * **Example:** A token for one machine
34
+ * ```typescript
35
+ * const user = yield* Archil.DiskUser("Indexer", { disk: dataset.diskId });
36
+ * // ARCHIL_MOUNT_TOKEN=<user.token> archil mount <disk> /mnt/data --region aws-us-east-1
37
+ * ```
38
+ *
39
+ * **Example:** An ECS task role that mounts with its own identity
40
+ * ```typescript
41
+ * const user = yield* Archil.DiskUser("Workers", {
42
+ * disk: dataset.diskId,
43
+ * principal: taskRole.roleArn,
44
+ * });
45
+ * ```
46
+ *
47
+ * **Example:** A read-only token that expires
48
+ * ```typescript
49
+ * const user = yield* Archil.DiskUser("Viewer", {
50
+ * disk: dataset.diskId,
51
+ * readOnly: true,
52
+ * expiresAt: "2027-01-01T00:00:00Z",
53
+ * });
54
+ * ```
55
+ *
56
+ * ### S3 Keys
57
+ * **Example:** A read-only access key pair for one disk
58
+ * ```typescript
59
+ * const reader = yield* Archil.DiskUser("Reader", {
60
+ * disk: dataset.diskId,
61
+ * type: "s3",
62
+ * readOnly: true,
63
+ * });
64
+ * // reader.accessKeyId, reader.secretAccessKey sign requests to
65
+ * // https://s3.green.us-east-1.aws.prod.archil.com/<disk id>/<key>
66
+ * ```
67
+ *
68
+ * @resource
69
+ * @product Disk
70
+ */
71
+ export const DiskUser = Resource("Archil.DiskUser");
72
+ const userNickname = (id, nickname) => nickname ? Effect.succeed(nickname) : createPhysicalName({ id, maxLength: 64, delimiter: "-" });
73
+ const lookupDiskUser = Effect.fn(function* (diskId, match) {
74
+ const { data } = yield* archil.getDisk({ id: diskId });
75
+ return (data.authorizedUsers ?? []).find((user) => match.identifier !== undefined
76
+ ? user.identifier === match.identifier
77
+ : match.principal !== undefined
78
+ ? user.principal === match.principal
79
+ : user.nickname === match.nickname);
80
+ });
81
+ /**
82
+ * The authorized user on a disk with this identifier, nickname or principal.
83
+ *
84
+ * For a few seconds after a user is added, some `getDisk` reads still list
85
+ * the disk without it (removals show at once). So a listed user exists, but
86
+ * a user we created (`match.identifier`) counts as missing only after reads
87
+ * across that window all miss it.
88
+ */
89
+ export const findDiskUser = Effect.fn(function* (diskId, match) {
90
+ const first = yield* lookupDiskUser(diskId, match);
91
+ if (first || match.identifier === undefined)
92
+ return first;
93
+ return yield* lookupDiskUser(diskId, match).pipe(Effect.repeat({
94
+ schedule: Schedule.spaced("500 millis"),
95
+ until: (user) => user !== undefined,
96
+ times: 14,
97
+ }));
98
+ });
99
+ const userType = (user) => user.principal !== undefined ? "awssts" : (user.type ?? "token");
100
+ const redacted = (value) => value === undefined ? undefined : typeof value === "string" ? Redacted.make(value) : value;
101
+ /** Add a token, S3, or IAM user to a disk. */
102
+ export const addDiskUser = Effect.fn(function* (diskId, user) {
103
+ const type = userType(user);
104
+ const limits = { readOnly: user.readOnly, expiresAt: user.expiresAt };
105
+ const { data } = yield* archil.addDiskUser({
106
+ id: diskId,
107
+ body: type === "awssts"
108
+ ? { type, principal: user.principal, ...limits, oneUse: user.oneUse }
109
+ : type === "s3"
110
+ ? { type, nickname: user.nickname, ...limits }
111
+ : { type, nickname: user.nickname, ...limits, oneUse: user.oneUse },
112
+ });
113
+ const missing = type === "token"
114
+ ? !data.token || !data.identifier
115
+ : type === "s3"
116
+ ? !data.s3AccessKeyId || !data.s3SecretKey
117
+ : false;
118
+ if (missing) {
119
+ return yield* new DiskUserUnexpectedResponse({
120
+ message: `Archil returned no ${type === "s3" ? "S3 keys" : "token"} for disk user ${user.nickname} on ${diskId}`,
121
+ });
122
+ }
123
+ return {
124
+ diskId,
125
+ type,
126
+ identifier: data.identifier ?? data.s3AccessKeyId ?? user.principal ?? "",
127
+ nickname: data.nickname ?? user.nickname,
128
+ principal: user.principal,
129
+ token: redacted(data.token),
130
+ accessKeyId: data.s3AccessKeyId,
131
+ secretAccessKey: redacted(data.s3SecretKey),
132
+ readOnly: data.readOnly ?? user.readOnly ?? false,
133
+ expiresAt: data.expiresAt ?? user.expiresAt,
134
+ oneUse: data.oneUse ?? user.oneUse ?? false,
135
+ };
136
+ });
137
+ /** Revoke a disk user. Revoking a missing user (or one on a deleted disk) succeeds. */
138
+ export const removeDiskUser = Effect.fn(function* (attrs) {
139
+ yield* archil
140
+ .removeDiskUser({
141
+ id: attrs.diskId,
142
+ userType: attrs.type,
143
+ identifier: attrs.type === "awssts" ? undefined : attrs.identifier,
144
+ principal: attrs.type === "awssts" ? attrs.principal : undefined,
145
+ })
146
+ .pipe(Effect.catchTag("NotFound", () => Effect.void));
147
+ });
148
+ export const DiskUserProvider = () => Provider.effect(DiskUser, Effect.gen(function* () {
149
+ return {
150
+ stables: [
151
+ "diskId",
152
+ "type",
153
+ "identifier",
154
+ "nickname",
155
+ "principal",
156
+ "token",
157
+ "accessKeyId",
158
+ "secretAccessKey",
159
+ "readOnly",
160
+ "expiresAt",
161
+ "oneUse",
162
+ ],
163
+ diff: Effect.fn(function* ({ id, olds, news, output }) {
164
+ if (!isResolved(news))
165
+ return undefined;
166
+ const nickname = output?.nickname ?? (yield* userNickname(id, olds?.nickname));
167
+ if (news.disk !== (output?.diskId ?? olds?.disk) ||
168
+ (news.nickname !== undefined && news.nickname !== nickname) ||
169
+ news.principal !== (output?.principal ?? olds?.principal) ||
170
+ userType(news) !== (output?.type ?? (olds ? userType(olds) : userType(news))) ||
171
+ (news.readOnly ?? false) !== (output?.readOnly ?? olds?.readOnly ?? false) ||
172
+ news.expiresAt !== (output?.expiresAt ?? olds?.expiresAt) ||
173
+ (news.oneUse ?? false) !== (output?.oneUse ?? olds?.oneUse ?? false)) {
174
+ return { action: "replace" };
175
+ }
176
+ return undefined;
177
+ }),
178
+ read: Effect.fn(function* ({ id, olds, output }) {
179
+ if (!output && !olds)
180
+ return undefined;
181
+ const diskId = output?.diskId ?? olds.disk;
182
+ const nickname = output?.nickname ?? (yield* userNickname(id, olds?.nickname));
183
+ const observed = yield* findDiskUser(diskId, {
184
+ identifier: output?.identifier,
185
+ principal: output?.principal ?? olds?.principal,
186
+ nickname,
187
+ }).pipe(Effect.catchTag("NotFound", () => Effect.undefined));
188
+ if (!observed)
189
+ return undefined;
190
+ return (output ?? {
191
+ diskId,
192
+ type: observed.type ?? "token",
193
+ identifier: observed.identifier ?? observed.principal ?? "",
194
+ nickname: observed.nickname ?? nickname,
195
+ principal: observed.principal,
196
+ // Secrets are only shown at creation; reconcile re-creates.
197
+ token: undefined,
198
+ accessKeyId: observed.s3AccessKeyId,
199
+ secretAccessKey: undefined,
200
+ readOnly: observed.readOnly ?? false,
201
+ expiresAt: observed.expiresAt,
202
+ oneUse: observed.oneUse ?? false,
203
+ });
204
+ }),
205
+ reconcile: Effect.fn(function* ({ id, news, output, session }) {
206
+ const nickname = output?.nickname ?? (yield* userNickname(id, news.nickname));
207
+ // Observe
208
+ const observed = yield* findDiskUser(news.disk, {
209
+ identifier: output?.identifier,
210
+ principal: news.principal,
211
+ nickname,
212
+ });
213
+ const type = userType(news);
214
+ const hasSecret = type === "awssts" ||
215
+ (type === "s3" ? output?.secretAccessKey !== undefined : output?.token !== undefined);
216
+ if (observed && output && hasSecret)
217
+ return output;
218
+ // Ensure — a user we hold no secret for (a lost create, or an
219
+ // adoption) is revoked and created again.
220
+ if (observed) {
221
+ yield* session.note(`Re-creating disk user ${nickname}...`);
222
+ yield* removeDiskUser({
223
+ diskId: news.disk,
224
+ type: observed.type ?? "token",
225
+ identifier: observed.identifier ?? "",
226
+ principal: observed.principal,
227
+ });
228
+ }
229
+ return yield* addDiskUser(news.disk, {
230
+ nickname,
231
+ principal: news.principal,
232
+ type: news.type,
233
+ readOnly: news.readOnly,
234
+ expiresAt: news.expiresAt,
235
+ oneUse: news.oneUse,
236
+ });
237
+ }),
238
+ delete: Effect.fn(function* ({ output }) {
239
+ yield* removeDiskUser(output);
240
+ }),
241
+ };
242
+ }));
243
+ //# sourceMappingURL=DiskUser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiskUser.js","sources":["../src/DiskUser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import * as Binding from "alchemy/Binding";
2
+ import type * as Effect from "effect/Effect";
3
+ import type { DiskDelegationsClient, ExecDiskClient } from "./Clients.ts";
4
+ import type { Disk } from "./Disk.ts";
5
+ export type { DiskDelegationsClient, ExecDiskClient, ExecResult, GrepOptions } from "./Clients.ts";
6
+ /**
7
+ * Run serverless commands against one disk, and search it, from a Worker,
8
+ * Lambda, or any other host. Each `exec` boots a fresh microVM with the
9
+ * disk mounted at `/mnt/archil`, runs the command to completion (up to five
10
+ * minutes), and shuts down, so you pay only for the call. Files the command
11
+ * writes stay on the disk.
12
+ *
13
+ * The host calls Archil with the API key you deploy with: Archil only
14
+ * creates API keys from the console and can't scope them to one disk.
15
+ *
16
+ * ### Running Commands
17
+ * **Example:** Count rows in a dataset from a Worker
18
+ * ```typescript
19
+ * export default class Api extends Cloudflare.Worker<Api>()(
20
+ * "Api",
21
+ * { main: import.meta.url },
22
+ * Effect.gen(function* () {
23
+ * const dataset = yield* Archil.ExecDisk(Dataset);
24
+ * return {
25
+ * fetch: Effect.gen(function* () {
26
+ * const result = yield* dataset.exec("wc -l /mnt/archil/*.csv");
27
+ * return HttpServerResponse.text(result.stdout);
28
+ * }),
29
+ * };
30
+ * }).pipe(Effect.provide(Archil.ExecDiskHttp)),
31
+ * ) {}
32
+ * ```
33
+ *
34
+ * ### Searching
35
+ * **Example:** Grep the whole disk in constant time
36
+ * ```typescript
37
+ * const hits = yield* dataset.grep({ pattern: "TODO", directory: "src", recursive: true });
38
+ * ```
39
+ *
40
+ * ### Recovering From a Crashed Mount
41
+ * A mounted client holds write delegations on the paths it writes. When it
42
+ * crashes without unmounting, reclaim them so other clients can write.
43
+ *
44
+ * **Example:** Revoke orphaned delegations
45
+ * ```typescript
46
+ * for (const d of yield* dataset.delegations()) {
47
+ * if (d.isOrphaned) yield* dataset.revokeDelegation(d);
48
+ * }
49
+ * ```
50
+ *
51
+ * @binding
52
+ * @product Disk
53
+ */
54
+ export interface ExecDisk extends Binding.Service<ExecDisk, "Archil.ExecDisk", (disk: Disk) => Effect.Effect<ExecDiskClient & DiskDelegationsClient>> {
55
+ }
56
+ export declare const ExecDisk: ExecDisk;
57
+ //# sourceMappingURL=ExecDisk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecDisk.d.ts","sources":["../src/ExecDisk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,OAAO,CAC/C,QAAQ,EACR,iBAAiB,EACjB,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,cAAc,GAAG,qBAAqB,CAAC,CACtE;CAAG;AAEJ,eAAO,MAAM,QAAQ,UAA+C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import * as Binding from "alchemy/Binding";
2
+ export const ExecDisk = Binding.Service("Archil.ExecDisk");
3
+ //# sourceMappingURL=ExecDisk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecDisk.js","sources":["../src/ExecDisk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AA6D3C,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAW,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import * as Layer from "effect/Layer";
2
+ import { ExecDisk } from "./ExecDisk.ts";
3
+ /** {@link ExecDisk} over Archil's HTTP API, usable from any host. */
4
+ export declare const ExecDiskHttp: Layer.Layer<ExecDisk, never, never>;
5
+ //# sourceMappingURL=ExecDiskHttp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecDiskHttp.d.ts","sources":["../src/ExecDiskHttp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAItC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,qEAAqE;AACrE,eAAO,MAAM,YAAY,qCAgBxB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Layer from "effect/Layer";
3
+ import { ApiAccess } from "./ArchilBindings.js";
4
+ import { makeDiskDelegationsClient, makeExecDiskClient } from "./Clients.js";
5
+ import { ExecDisk } from "./ExecDisk.js";
6
+ /** {@link ExecDisk} over Archil's HTTP API, usable from any host. */
7
+ export const ExecDiskHttp = Layer.effect(ExecDisk, Effect.gen(function* () {
8
+ const access = yield* ApiAccess;
9
+ return Effect.fn(function* (disk) {
10
+ const authorize = yield* access();
11
+ const diskId = yield* disk.diskId;
12
+ return {
13
+ ...makeExecDiskClient(diskId, authorize),
14
+ ...makeDiskDelegationsClient(Effect.map(diskId, (id) => ({ disk: id })), authorize),
15
+ };
16
+ });
17
+ }));
18
+ //# sourceMappingURL=ExecDiskHttp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecDiskHttp.js","sources":["../src/ExecDiskHttp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CACtC,QAAQ,EACR,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAU;QACpC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAClC,OAAO;YACL,GAAG,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC;YACxC,GAAG,yBAAyB,CAC1B,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAC1C,SAAS,CACV;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}