Skip to content

fix: four of the #280 follow-ups: mint credentials, listing dedupe, ensure identity, launch_image_arn - #540

Merged
laithalsaadoon merged 5 commits into
mainfrom
fix/parity-followups
Oct 10, 2026
Merged

laithalsaadoon merged 5 commits into
mainfrom
fix/parity-followups

Conversation

@laithalsaadoon

Copy link
Copy Markdown
Owner

What and why

Four of #280's "Follow-ups found during the burn-down", each in its own commit with its failing-first test. Based on main at cae2ec7, which carries #536 (the per-crate semver gates, merged as def2815), so those gates judge this change too.

  • A credential failure during a token mint is ERR_CREDENTIALS (c3046d4). ProxyAuth::token_for reclassified every minter failure as WireKind::AuthTokenMint, so a mint the control plane refused for the caller's identity was ERR_RETRYABLE (exit 3) with a message promising "the identical request may succeed". A minter failure of kind Credentials keeps it, with the minter's reason as its source; a throttle and every other mint failure stay retryable.
  • ControlPlane::list_microvms lists each VM once (7148700). The service can return one VM on two pages while VMs change state (docs/PLATFORM.md, measured 2026-10-01 by fix(conformance): CLI-8 names the run's VM from its history, and counts a listing's VMs once #500), and the listing concatenated pages, so ls --remote and both bindings' ControlPlane.list could list a VM twice. A repeat keeps the VM's first position and the entry read last, the newer reading of its state.
  • An ensured image's name covers its create-only fields (499ae33). The identity hash left out identity repair, inherit_workdir, the hook timeouts and the log group and stream, so a reuse could return an image built without a field the caller asked for (from feat(cli): build --reuse, run's build and agent-up go through core's ensure_image, and the aws s3 cp upload is gone (#258) #454). prepare names the image for create_identity_hash of the exact create request it sends; the stream's tag moves to microvms-ensure-image/2, so every ensured image, the agent recipes' included, is renamed once. The public pinned_identity_hash and image_identity_hash keep their signatures and answer the identity with the create request's defaults. Tags stay out of the name.
  • Both bindings expose launch_image_arn (707f785). Python's Sandbox.launch_image_arn property and Node's Sandbox.launchImageArn() read core's Sandbox::launch_image_arn (fix: Sandbox::run resolves a bare image name to its ARN, for every surface (#253) #401), with a launch-image-arn row in verify/parity/capabilities.toml naming all four surfaces (the CLI's is run --image).

Changelog: changelog.d/280.fixed.md (three entries) and changelog.d/280.added.md.

Size: 424 changed lines of product code against origin/main, past the soft cap, because the owner asked for these four #280 boxes as one branch. The change can be split: each box is its own commit, so review can take it commit by commit, and the ensure rename (499ae33) is most of the lines.

Verified offline only. Nothing here was exercised against AWS; the dedupe follows the 2026-10-01 measurement, and the mint path's credential class is asserted against a fake minter.

Evidence

  • Main moved to 8d87a3b (nightly chore(deps): nightly rollup 2026-10-09 #538, docs docs: correct cli.md's microvm.toml section and envelope key lists against the code #539) after the rebase. b69c0ee merges into it without conflicts, and TMPDIR=<scratch>/t mise run -c check on that merged tree exits 0 in 310 s (cold build).

  • cargo fmt --all -- --check

  • cargo clippy --all-targets -- -D warnings (through mise run check)

  • cargo test --all (through mise run check; the workspace's Rust tests also pass with cargo test --workspace --exclude microvms-py --exclude microvms-js --no-fail-fast)

  • TMPDIR=<scratch>/t mise run -c check at the final commit (b69c0ee, rebased onto cae2ec7): exit 0 in 110 s (warm; the cold run before the guards re-proof, at 10c21e7, exited 0 in 301 s). mise run semver:check exits 0 too: all five comparisons against 0.11.0 pass (196 checks: 196 pass, 58 skip each). Before the rebase, a run failed lint on a clippy::type_complexity in the new ensure test, fixed by a type alias in 499ae33.

  • Both binding suites, built the way bindings:py and bindings:js build them: pytest 461 passed, 1 skipped; node --test 349 passed, 0 failed.

  • ./tools/generate-py-stubs.py and mise run dts regenerated microvms.pyi and index.d.ts; stubs:check and dts:check pass in check.

Failing first, each watched red before its fix:

  • session::proxy::tests::a_credential_failure_during_a_mint_is_err_credentials_not_retryable: left: Retryable, right: Credentials.
  • control::microvm::tests::a_vm_the_fleet_listing_meets_on_two_pages_is_listed_once: left: ["mvm-a", "mvm-moved", "mvm-moved", "mvm-b"].
  • control::ensure::tests::each_create_only_field_names_a_different_image: repair_guest_identity is create-only, so it is identity, both names task-48daea63e51c.
  • test_launch_image_arn_names_the_image_the_launch_sent: AttributeError: 'microvms.Sandbox' object has no attribute 'launch_image_arn'; node's launchImageArn names the image the launch sent: TypeError: sandbox.launchImageArn is not a function.

Parity

  • No public name changed on any surface (core, CLI commands, microvms.pyi, index.d.ts). Python gains Sandbox.launch_image_arn and Node Sandbox.launchImageArn(); core's public paths are unchanged (core-api:check passes).
  • verify/parity/capabilities.toml updated: the launch-image-arn row names core, run --image, Sandbox.launch_image_arn and Sandbox.launchImageArn. mise run parity:check passes.

The three image-name cases in verify/parity/cases/ take the renamed images (parity-task-178447f17502, agent-vm-claude-code-cb158b8e2c7d, agent-vm-claude-code-codex-937344ac9c1b); core, the CLI and both bindings' runners answer them.

Guards

mise run fail-to-pass -- --jobs 4 --emit parity-followups against cae2ec73845c, the merge base with origin/main, wrote six entries into verify/guards/faults/parity-followups.toml with their patches:

fired: f2p-a-created-image-carries-every-field-of-the-request (9.2 s)
fired: f2p-each-create-only-field-names-a-different-image (9.1 s)
fired: f2p-a-vm-the-fleet-listing-meets-on-two-pages-is-listed-once (9.4 s)
fired: f2p-a-credential-failure-during-a-mint-is-err-credentials (2.9 s)
fired: f2p-test-launch-image-arn-names-the-image-the-launch-sent (15.7 s)
fired: f2p-launchimagearn-names-the-image-the-launch-sent (25.3 s)

control::ensure::tests::an_ensure_from_a_create_request_keeps_its_fields changed too (its direct ensure takes the same log group and identity repair as the create it compares to) and passes with the fix taken out, so it proves nothing about the fix and has no entry; the two ensure entries above guard the rename.

Follow-ups

Platform claims

  • Not applicable: this changes no claim about AWS behavior.

Scope

  • This is not an orchestrator, a fork implementation, or AgentCore parity work
    (see docs/STRATEGY.md).

laithalsaadoon and others added 5 commits October 9, 2026 02:31
…IALS (#280)

`ProxyAuth::token_for` reclassified every minter failure as
`WireKind::AuthTokenMint`, which is `ERR_RETRYABLE`, so a mint the control
plane refused for the caller's identity told the caller to retry, with a
message that said both "waiting will not fix this" (the credential's own
text) and "the identical request may succeed". A credential failure keeps
`ErrorKind::Credentials` now, with the minter's reason as its source; every
other mint failure, a throttle among them, stays retryable.

`a_credential_failure_during_a_mint_is_err_credentials_not_retryable` fails
on the base with `left: Retryable, right: Credentials` and passes with the
fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ges carry it (#280)

The service can return one VM on two pages of a `ListMicrovms` walk while
VMs change state (measured 2026-10-01, recorded in docs/PLATFORM.md by
#500), and `list_microvms_matching` extended its result with every page, so
`ls --remote` and both bindings' `ControlPlane.list` could list it twice. A
repeat now replaces the earlier entry in place: the VM keeps the position it
was first listed at and the entry read last, the newer reading of its state.

`a_vm_the_fleet_listing_meets_on_two_pages_is_listed_once` fails on the
base with `left: ["mvm-a", "mvm-moved", "mvm-moved", "mvm-b"]` and passes
with the fix. Verified offline only: no live run has listed a VM twice
through the client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
)

`ensure_image` hashed the artifact, the base, a pinned base version and the
size class into the image's name, and left out what `CreateMicrovmImage`
fixes for the image's life: identity repair, `inherit_workdir`, the run and
build hook timeouts, and the log group and stream. A ready image under the
name was reused whatever those were, so a caller asking for identity repair
could get an image built without it (from #454).

`prepare` builds the unnamed create request first and names the image for
`create_identity_hash` of exactly that request, so every field it carries
is read once. The stream's domain tag moves to `microvms-ensure-image/2`
and tags each create-only field, length-prefixed, with an absent optional
distinct from an empty one. Every ensured image is renamed once, which is
the fix: an image named by the old stream may lack a field its next caller
asks for. `pinned_identity_hash` and `image_identity_hash` keep their
signatures and answer the identity of an image with the create request's
defaults; the agent recipe's `image_name_for` names its request's own
fields, so its two-step path and its ensure still name one image. Tags stay
out of the name.

`each_create_only_field_names_a_different_image` fails on the base with
`repair_guest_identity is create-only, so it is identity` (left and right
both `task-48daea63e51c`) and passes with the fix. Two tests change with the
behavior: `a_created_image_carries_every_field_of_the_request` asserts the
configured name differs where it asserted it was equal, and
`an_ensure_from_a_create_request_keeps_its_fields` gives the direct ensure
the same log group and identity repair as the create it compares to. The
three image-name parity cases take the new names, which core and the CLI
runner answer. Verified offline only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e's (#280)

#401 added `Sandbox::launch_image_arn` to core for the image a launch
resolved, and the CLI's `run --image` reports it, but neither binding
exposed it, so a Python or Node caller launching by name could not read the
ARN the name became. Python gets a `launch_image_arn` property and Node an
async `launchImageArn()`, the form napi gives every Sandbox accessor, both
reading core's value. The capability table gets its `launch-image-arn` row
naming all four surfaces, and the stub and declarations are regenerated.

`test_launch_image_arn_names_the_image_the_launch_sent` fails on the base
with `AttributeError: 'microvms.Sandbox' object has no attribute
'launch_image_arn'`, and the node test `launchImageArn names the image the
launch sent` with `TypeError: sandbox.launchImageArn is not a function`;
both pass with the change, as do both suites (pytest 461 passed, 1 skipped;
node 349 passed) and `tools/check-parity.py`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`mise run fail-to-pass -- --jobs 4 --emit parity-followups` against
334a668, the merge base with origin/main, proved six of the branch's new or
changed tests: each passes on the head and fails with the branch's product
hunks reversed, and each becomes an entry in
verify/guards/faults/parity-followups.toml with its patch, so CI's `guards`
job fires it again.

fired: f2p-a-created-image-carries-every-field-of-the-request
fired: f2p-each-create-only-field-names-a-different-image
fired: f2p-a-vm-the-fleet-listing-meets-on-two-pages-is-listed-once
fired: f2p-a-credential-failure-during-a-mint-is-err-credentials
fired: f2p-test-launch-image-arn-names-the-image-the-launch-sent
fired: f2p-launchimagearn-names-the-image-the-launch-sent

`an_ensure_from_a_create_request_keeps_its_fields` changed with the rename
and passes with the fix taken out, so it gets no entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 9, 2026 14:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@laithalsaadoon
laithalsaadoon merged commit 0552d8c into main Oct 10, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants