@evident-ai/runner-cdk 3.5.2-dev.7130f36 → 3.5.2-dev.81383cc

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 (33) hide show
  1. package/README.md +89 -39
  2. package/dist/controller-lambda/handler.js +13 -13
  3. package/dist/image-version-pruner-lambda/handler.js +28250 -0
  4. package/dist/image-version-reporter-lambda/handler.js +15 -8
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +3 -2
  7. package/dist/microvm/constants.d.ts +1 -1
  8. package/dist/microvm/constants.js +7 -4
  9. package/dist/microvm/construct.d.ts +12 -8
  10. package/dist/microvm/construct.js +33 -26
  11. package/dist/microvm/controller/handle-doorbell.d.ts +2 -2
  12. package/dist/microvm/controller/handle-doorbell.js +2 -2
  13. package/dist/microvm/image/stage-context.d.ts +13 -38
  14. package/dist/microvm/image/stage-context.js +30 -120
  15. package/dist/microvm/image-version-pruner/construct.d.ts +13 -0
  16. package/dist/microvm/image-version-pruner/construct.js +79 -0
  17. package/dist/microvm/image-version-pruner/handler.d.ts +20 -0
  18. package/dist/microvm/image-version-pruner/handler.js +116 -0
  19. package/dist/microvm/image-version-reporter/construct.d.ts +1 -1
  20. package/dist/microvm/image-version-reporter/construct.js +3 -3
  21. package/dist/microvm/image-version-reporter/handler.d.ts +2 -2
  22. package/dist/microvm/image-version-reporter/handler.js +9 -7
  23. package/dist/microvm/shapes.d.ts +10 -21
  24. package/dist/microvm/shapes.js +10 -17
  25. package/package.json +3 -3
  26. package/dist/microvm-image-context/Dockerfile +0 -190
  27. package/dist/microvm-image-context/hook-server.js +0 -286
  28. package/dist/microvm-image-context/hooks/common.sh +0 -958
  29. package/dist/microvm-image-context/hooks/resume +0 -81
  30. package/dist/microvm-image-context/hooks/run +0 -95
  31. package/dist/microvm-image-context/hooks/session-db-maintenance.mjs +0 -69
  32. package/dist/microvm-image-context/hooks/suspend +0 -21
  33. package/dist/microvm-image-context/hooks/terminate +0 -38
package/README.md CHANGED
@@ -9,9 +9,9 @@ Reusable AWS CDK constructs for running an [Evident](https://evident.run) agent
9
9
  `desiredCount 0`, and an HMAC-authenticated waker Lambda scales it back up on the next
10
10
  message. You pay for the time the agent is actually working.
11
11
  - **`EvidentMicrovmConstruct`** — a per-session AWS Lambda MicroVM that boots on demand
12
- and suspends between messages. Installing this package is all you
13
- need: the image build context ships inside it (see [The MicroVM image](#the-microvm-image)
14
- below), so there is no checkout of the source repository involved. See
12
+ and suspends between messages. You provide a build-context directory and a full source
13
+ checkout to `stageMicrovmBuildContext`, then pass its returned directory as
14
+ `buildContextPath` (see [The MicroVM image](#the-microvm-image) below). See
15
15
  [the AWS runner doc](https://evident.run/docs/aws-runner) for the full picture of both
16
16
  strategies.
17
17
 
@@ -99,6 +99,26 @@ For the full end-to-end walkthrough for this construct, see
99
99
  | `agentSecret`, `wakerSecret` | `secretsmanager.ISecret` | Any Secrets Manager secret. |
100
100
  | `availableSecretKeys` | `Set<string>` | Keys present in the agent secret. Every listed key is injected; `EVIDENT_RUNNER_KEY` and `EVIDENT_AGENT_KEY` are injected from the `EVIDENT_AGENT_KEY` field, and `GH_TOKEN` is also injected for adopters that do not enumerate their secret. |
101
101
 
102
+ ### MicroVM props
103
+
104
+ | Prop | Type | Notes |
105
+ | --- | --- | --- |
106
+ | `buildContextPath` | `string` | Directory containing your Dockerfile and every file it copies, normally the result of `stageMicrovmBuildContext()`. |
107
+ | `baseImageArn` / `baseImageVersion` | `string` | The AWS-managed base MicroVM image values from `aws lambda-microvms list-managed-microvm-images`. |
108
+ | `controllerSigningSecret` | `secretsmanager.ISecret` | Secret containing the shared HMAC key under the `CONTROLLER_SIGNING_SECRET` JSON field. |
109
+ | `hooksPort` / `hookTimeoutSeconds` | `number` | Values exported by the base image contract. |
110
+ | `shapes` | `readonly MicrovmShape[]?` | Shape catalogue to build. Defaults to the committed catalogue. |
111
+ | `runnerSecret` | `secretsmanager.ISecret?` | Optional JSON secret whose values are exported by `/run`. |
112
+ | `runnerOpencodeConfigPath` | `string?` | Optional baked OpenCode configuration path. |
113
+ | `gitUserName` / `gitUserEmail` | `string?` | Optional git identity for agent commits. |
114
+ | `extraImageEnvironment` | `Record<string,string>?` | Non-secret values baked into every VM launched from the image version. |
115
+ | `evidentApiUrl` / `evidentRunnerId` | `string?` | Supply both to report published image versions to Evident, or omit both. |
116
+ | `imageVersionPruning` | `boolean?` | Opts into construct-owned pruning for this deployment's images. Uses the engine defaults; omitting it creates no pruning resources. |
117
+
118
+ The `DoorbellSecret` CloudFormation logical ID remains stable for Evident's own
119
+ default stack. It identifies the deployed secret resource, not the customer-facing
120
+ name of the signing key.
121
+
102
122
  ### Two deliberate "no default" choices
103
123
 
104
124
  - **The endpoints are required.** Defaulting them would either bake *our* dev environment
@@ -116,58 +136,73 @@ built from a `Dockerfile` you control. The generic runner image lives separately
116
136
 
117
137
  ## The MicroVM image
118
138
 
119
- `EvidentMicrovmConstruct`'s `imageSource` is a **local directory** holding the image build
120
- context, which `cdk deploy` zips and uploads. The Lambda MicroVM service then builds the
121
- image in *your* account, from a base image ARN you discover there — so, unlike the Fargate
122
- strategy, there is no registry image to pull.
139
+ ### Prune image versions
123
140
 
124
- The context has three parts: this package supplies the Dockerfile, the per-phase hook
125
- scripts and the bundled hook server, published inside the tarball at
126
- `dist/microvm-image-context/`; **your** repository is baked in as the agent's workspace;
127
- and an optional overlay supplies deployment-specific build steps. `stageMicrovmImageContext()`
128
- puts them together:
141
+ MicroVM image versions are quota-bound. Opt into construct-owned pruning with one
142
+ property:
143
+
144
+ ```ts
145
+ new EvidentMicrovmConstruct(this, 'Runner', {
146
+ // ...other required MicroVM props
147
+ imageVersionPruning: true,
148
+ });
149
+ ```
150
+
151
+ This bounds the per-image version quota (`L-F8BECE9C`) for this deployment's shapes only.
152
+ Retention follows the engine defaults, and pruning runs before the image publish for the
153
+ deploy that invokes it. The custom-resource Lambda writes per-image verdicts and a summary
154
+ to CloudWatch Logs. Use the `prune-microvm-image-versions` CLI for deployments that do not
155
+ use this construct or that need non-default retention; see the
156
+ `@evident-ai/lambda-microvm-cdk` package README for its flags and safety semantics.
157
+
158
+ `EvidentMicrovmConstruct`'s `buildContextPath` is a **local directory** holding the
159
+ Dockerfile you control and everything it copies. `cdk deploy` zips and uploads that
160
+ directory, and the Lambda MicroVM service builds the image in *your* account. Start the
161
+ Dockerfile from a pinned `ghcr.io/sroze/evident-microvm-base:X.Y.Z` tag; the base image
162
+ contains the hook server, lifecycle hooks and common agent tooling.
163
+
164
+ `stageMicrovmBuildContext()` combines your build-context directory with a full checkout
165
+ of the workspace in a fresh temporary directory. The workspace is written at
166
+ `workspace/`, and the returned path is the value for `buildContextPath`:
129
167
 
130
168
  ```ts
131
- import path from 'node:path';
132
169
  import {
133
170
  EvidentMicrovmConstruct,
134
171
  HOOKS_PORT,
135
172
  HOOK_TIMEOUT_SECONDS,
136
- stageMicrovmImageContext,
173
+ stageMicrovmBuildContext,
137
174
  } from '@evident-ai/runner-cdk';
138
175
 
176
+ const buildContextPath = stageMicrovmBuildContext({
177
+ // A full (non-shallow) clone: the agent branches, commits and opens PRs.
178
+ workspaceRepositoryPath: '/path/to/your/checkout',
179
+ // Credential-free: the token the agent pushes with arrives per-session.
180
+ workspaceOriginUrl: 'https://github.com/acme/widgets.git',
181
+ buildContextPath: '/path/to/your/microvm-build-context',
182
+ });
183
+
139
184
  new EvidentMicrovmConstruct(this, 'Runner', {
140
- imageSource: stageMicrovmImageContext({
141
- // A full (non-shallow) clone: the agent branches, commits and opens PRs.
142
- repositoryPath: '/path/to/your/checkout',
143
- // Credential-free — this string ships inside the shared snapshot. The
144
- // token the agent pushes with arrives per-session, never baked in.
145
- originUrl: 'https://github.com/acme/widgets.git',
146
- destination: path.join(__dirname, '..', 'build', 'image'),
147
- // Optional deployment-specific installs and build warm-up.
148
- overlayDir: '/path/to/microvm-overlay',
149
- }),
185
+ buildContextPath,
150
186
  // Must match the published image these were baked into, so export them
151
187
  // rather than restating the numbers.
152
188
  hooksPort: HOOKS_PORT,
153
189
  hookTimeoutSeconds: HOOK_TIMEOUT_SECONDS,
154
190
  baseImageArn,
155
191
  baseImageVersion,
156
- doorbellSecret,
192
+ controllerSigningSecret,
157
193
  runnerSecret,
158
194
  runnerOpencodeConfigPath: 'opencode.runner.jsonc',
159
195
  });
160
196
  ```
161
197
 
162
- Pass `overlayDir` to add deployment-specific build steps to the staged image. The
163
- directory provides `setup-root` for root-owned installs and `setup-workspace` for
164
- dependency installation and workspace build warm-up. See the [MicroVM image
165
- README](https://github.com/evident-run/evident-run/blob/main/runner/docker-images/microvm/README.md)
166
- for the full overlay contract.
198
+ Write project-specific installation and build steps in your Dockerfile. The [MicroVM base
199
+ image README](../../runner/docker-images/microvm/README.md) documents the consumer
200
+ contract, including the required `USER`, `WORKDIR`, ownership and `git reset --quiet`
201
+ steps.
167
202
 
168
- The image bakes your repository checked out but not installed and makes no assumptions about
169
- its package manager. To speed up first boot, install dependencies from your overlay's
170
- `setup-workspace`; otherwise, the agent installs them on first use.
203
+ The staged image includes your repository checkout, while your Dockerfile controls its
204
+ package manager and build warm-up. Do not copy credentials into the build context or bake
205
+ them into image environment variables.
171
206
 
172
207
  | MicroVM prop | Omitted behavior |
173
208
  | --- | --- |
@@ -175,12 +210,27 @@ its package manager. To speed up first boot, install dependencies from your over
175
210
  | `runnerOpencodeConfigPath` | OpenCode uses the baked project configuration. Relative paths resolve from the workspace; absolute paths resolve in the image. |
176
211
  | `extraImageEnvironment` | Non-secret values baked into every VM launched from this image version; every VM can read them, so never put secrets here. |
177
212
  | `gitUserName` / `gitUserEmail` | The hook uses the Evident bot defaults for git identity. |
178
- | `evidentApiUrl` / `evidentRunnerId` | No deploy-time report of the published image version — a byte-identical template to not having these props at all. Both non-secret (a URL, a public pool UUID) and both required together: set them if you have an Evident runner id configured for this provisioner, so each deploy that publishes a new image version tells Evident about it (a CloudFormation custom resource, HMAC-signed with `doorbellSecret`). A failure to report never fails your deploy — it warns and Evident reads that provisioner as *unknown*, never as up to date or stale. |
179
-
180
- `extraImageEnvironment` is the runtime counterpart to an overlay. Use it when an
181
- overlay-installed component needs an environment variable after the VM boots. The
182
- values are baked into every VM launched from that image version and are readable by
183
- all of them, so never put a secret in this prop.
213
+ | `evidentApiUrl` / `evidentRunnerId` | No deploy-time report of the published image version — a byte-identical template to not having these props at all. Both non-secret (a URL, a public pool UUID) and both required together: set them if you have an Evident runner id configured for this provisioner, so each deploy that publishes a new image version tells Evident about it (a CloudFormation custom resource, HMAC-signed with `controllerSigningSecret`). A failure to report never fails your deploy — it warns and Evident reads that provisioner as *unknown*, never as up to date or stale. |
214
+
215
+ `extraImageEnvironment` is the runtime environment for the image. Values are baked into
216
+ every VM launched from that image version and are readable by all of them, so never put a
217
+ secret in this prop.
218
+
219
+ ## Breaking changes in this release
220
+
221
+ - `stageMicrovmImageContext` is removed. Use `stageMicrovmBuildContext()` with your
222
+ Dockerfile and build context.
223
+ - `imageSource` is renamed to `buildContextPath`.
224
+ - `MicrovmShape.constructId` is removed. CloudFormation child identity derives from
225
+ the shape `name`.
226
+ - `doorbellSecret` is renamed to `controllerSigningSecret`.
227
+ - The default shape's `imageName` changes to `evident-microvm-standard`. The
228
+ `AWS::Lambda::MicrovmImage` resource, its auto-created build role and execution
229
+ role, and both roles' default policies are replaced with the new shape identity.
230
+ - The JSON field in the caller-supplied Secrets Manager secret changes from
231
+ `DOORBELL_SECRET` to `CONTROLLER_SIGNING_SECRET`. Rename that field in your own
232
+ secret. If you do not, the controller reads no signing key and every doorbell
233
+ returns HTTP 401 at runtime; TypeScript cannot catch this field-key change.
184
234
 
185
235
  ## Status / limitations
186
236
 
@@ -50036,13 +50036,13 @@ async function shouldRecreateForNewerImage(doorbellRequest, shape, runningVersio
50036
50036
  async function handleDoorbell({
50037
50037
  rawBody,
50038
50038
  signatureHeader,
50039
- doorbellSecret,
50039
+ controllerSigningSecret,
50040
50040
  shapes,
50041
50041
  microvm,
50042
50042
  sleep: sleep4,
50043
50043
  random
50044
50044
  }) {
50045
- if (!verifyEvidentSignature(rawBody, signatureHeader, doorbellSecret)) {
50045
+ if (!verifyEvidentSignature(rawBody, signatureHeader, controllerSigningSecret)) {
50046
50046
  return decide({
50047
50047
  statusCode: 401,
50048
50048
  action: "rejected",
@@ -50413,20 +50413,20 @@ function parseShapeCatalogue(raw) {
50413
50413
  // src/microvm/controller/handler.ts
50414
50414
  var microvms = new import_client_lambda_microvms.LambdaMicrovmsClient({});
50415
50415
  var secrets = new import_client_secrets_manager.SecretsManagerClient({});
50416
- var cachedDoorbellSecret;
50417
- async function getDoorbellSecret(secretArn, key) {
50418
- if (cachedDoorbellSecret !== void 0) {
50419
- return cachedDoorbellSecret;
50416
+ var cachedControllerSigningSecret;
50417
+ async function getControllerSigningSecret(secretArn, key) {
50418
+ if (cachedControllerSigningSecret !== void 0) {
50419
+ return cachedControllerSigningSecret;
50420
50420
  }
50421
50421
  const { SecretString } = await secrets.send(new import_client_secrets_manager.GetSecretValueCommand({ SecretId: secretArn }));
50422
50422
  if (!SecretString) {
50423
- throw new Error(`doorbell secret ${secretArn} has no SecretString`);
50423
+ throw new Error(`controller signing secret ${secretArn} has no SecretString`);
50424
50424
  }
50425
50425
  const value = JSON.parse(SecretString)[key];
50426
50426
  if (typeof value !== "string" || value === "") {
50427
- throw new Error(`doorbell secret ${secretArn} is missing a non-empty '${key}' field`);
50427
+ throw new Error(`controller signing secret ${secretArn} is missing a non-empty '${key}' field`);
50428
50428
  }
50429
- cachedDoorbellSecret = value;
50429
+ cachedControllerSigningSecret = value;
50430
50430
  return value;
50431
50431
  }
50432
50432
  function createRuntimeMicrovm(executionRoleArn) {
@@ -50501,9 +50501,9 @@ function requireEnv(name) {
50501
50501
  }
50502
50502
  var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
50503
50503
  var handler = async (event) => {
50504
- const doorbellSecret = await getDoorbellSecret(
50505
- requireEnv("DOORBELL_SECRET_ARN"),
50506
- requireEnv("DOORBELL_SECRET_KEY")
50504
+ const controllerSigningSecret = await getControllerSigningSecret(
50505
+ requireEnv("CONTROLLER_SIGNING_SECRET_ARN"),
50506
+ requireEnv("CONTROLLER_SIGNING_SECRET_KEY")
50507
50507
  );
50508
50508
  const shapes = parseShapeCatalogue(requireEnv("MICROVM_SHAPES"));
50509
50509
  const executionRoleArn = requireEnv("MICROVM_EXECUTION_ROLE_ARN");
@@ -50511,7 +50511,7 @@ var handler = async (event) => {
50511
50511
  const { statusCode, body } = await handleDoorbell({
50512
50512
  rawBody,
50513
50513
  signatureHeader: event.headers?.["x-evident-signature"],
50514
- doorbellSecret,
50514
+ controllerSigningSecret,
50515
50515
  shapes,
50516
50516
  microvm: createRuntimeMicrovm(executionRoleArn),
50517
50517
  sleep: sleep3,