Skip to content

fix: staging validation fixes for remote bindings and setup - #865

Merged
alongubkin merged 10 commits into
mainfrom
alon/alien-1219-staging-fixes
Oct 5, 2026
Merged

alongubkin merged 10 commits into
mainfrom
alon/alien-1219-staging-fixes

Conversation

@alongubkin

Copy link
Copy Markdown
Member

Fixes found while validating recent changes end to end. Linear: ALIEN-1219.

Remote bindings while an update is pending or failed

When a deployment's desired release differed from its current one (for example after a failed update), /v1/bindings/resolve loaded the desired release to check whether a sandbox may share the identity. If the release store couldn't return it, the manager turned that into an internal error, and every remote binding for the deployment (Storage, Key, AI, KV and Queue) answered 500 with no log.

The manager now returns REMOTE_BINDING_DESIRED_RELEASE_UNAVAILABLE: a retryable 503 that names the deployment and the release. It logs the store's error with warn! and doesn't pass it to the caller. The binding is still refused, so the sandbox check is never skipped.

Tests: a missing desired release and a failing store both return the 503, with no source attached; a readable desired release still has its sandbox check enforced.

More fixes from the same validation will be added to this PR.

🤖 Generated with Claude Code

… is unreadable

Remote binding resolution checks the deployment's desired release for a
remote sandbox that could share the Remote Bindings identity. When that
release could not be loaded (for example after a failed update), the
manager returned an internal error, which callers saw as a sanitized 500
with nothing logged.

Refuse with REMOTE_BINDING_DESIRED_RELEASE_UNAVAILABLE instead: a
retryable 503 that names the deployment and release. The store error is
logged and not chained into the response.

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

greptile-apps Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds error handling for remote binding validation.

The PR appears safe to merge.

Summary

The PR changes remote-binding resolution to refuse access with a retryable 503 when a deployment’s desired release cannot be loaded, while logging store failures server-side. New tests cover missing and failing release reads and retain the sandbox check for readable releases.

Reviews (1) · Last reviewed commit: "fix: return a retryable error when a rem..."

alongubkin and others added 9 commits October 5, 2026 00:54
…ault network

A static `UseDefault` AWS network only declared `data.aws_vpc.<label>_default`
and `data.aws_subnets.<label>_default` when the stack also held a setup-owned
Postgres or a managed EKS cluster. The shared network helpers (`vpc_id_expr`,
`private_subnet_ids_expr`) reference those data sources for every
`UseDefault` network, so any other consumer, such as a compute cluster for a
Container, rendered a module that failed `terraform validate`.

Declare the data sources whenever the network is a static default network,
and add a generator test that renders a compute cluster consuming the network
helpers on both a static default and a dynamic network and runs
`terraform validate` on each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alien deploy drives setup up to provisioning and then hands the deployment
to the manager. It printed "Deployment is running." and exited 0 at that
point, even when provisioning later blocked on a deployer secret or failed.

After the handoff, poll the deployment until it is running. A failed or
deleted deployment exits non-zero with the deployment's own error, a
deployment waiting for secrets or machines prints what it is blocked on,
and the wait gives up after 30 minutes naming the last status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sandbox with a privileged supervisor enforces its declared egress in
the guest, so the MicroVM itself runs with open egress. The setup
emitters already read `cloud_egress()`, but the direct-deployment seed
read the declared egress: `allowDomains` was refused outright and a
supervised `deny` asked for a connector the template never creates.

The registration parity test now covers supervised `allowDomains` and
`deny` sandboxes, so the emitted and direct registrations stay equal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`alien destroy` resolved the manager with the user's login and reused that
client for the setup-teardown sync acquire. The platform only lets manager
and deployment-scoped tokens use the sync protocol, so destroying a
teardown-required deployment failed with 403. Build the teardown client
from the tracked deployment's token, as `alien deploy` already does since
#636; the delete request itself still goes out as the operator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…od and deployer inputs

alien onboard --airgapped posted /v1/initialize with only a name and
platform. A manager backed by a control plane that picks the setup item
and cluster ownership from the request refused it, and required deployer
inputs had no way in: deployer inputs are answered on a setup page, which
an air-gapped site doesn't have.

Register as the chart's Operator does (setupItem deployment, setupMethod
helm), and route --input values for deployer-only inputs into the
registration. Required ones are prompted for or fail fast; deployer
secrets are still refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A profile granted sandbox/management or sandbox/execute on a sandbox
never received the IAM for it: the CloudFormation and Terraform sandbox
emitters wrote no per-profile policies (the storage, vault and kv
emitters do), and the AWS controller never applied resource-scoped
permissions. A Worker creating a session was denied lambda:RunMicrovm.

Both emitters now attach each profile's sandbox/* sets to its service
account role, scoped by name to the sandbox's image, for Frozen and Live
sandboxes. The controller applies them after a direct setup builds a
Frozen sandbox's image.

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

Deleting a deployment whose setup failed before the secrets vault was
provisioned failed with "No binding configured for 'secrets'": the
cleanup still tried to load the vault to delete deployment-owned keys.
A vault without a binding was never written to, so the cleanup now
clears the sync metadata and skips it.

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

A status report wrote its telemetry batches to the backend one at a
time. Backends that acknowledge a write only once it is flushed take
seconds per batch, so a site with a backlog never got an answer before
a load balancer's 60s timeout and never caught up. When the client gave
up, the dropped handler left a batch the backend had already taken
outside the mark, so the next report sent it again.

Batches are now written eight at a time with the mark advancing only
over the batches that completed in order. No new batch starts after 45
seconds; the report answers with the partial telemetryThrough and the
site sends the rest next time. The forwarding runs in its own task, so
a disconnecting client can't cancel it between the backend taking a
batch and the mark covering it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l to send

alien-deploy sync sent the waiting reports before downloading the next
update and stopped on the first failure, so one report the manager
couldn't take held back every later update to the site, including one
that would fix it.

The update is now downloaded (and, on a machine that reaches both
sides, installed) regardless. The report stays in from-site/ and sync
exits non-zero at the end, since the vendor still lacks the site's
state and telemetry and the site's buffer isn't freed until it lands.

Reports also follow the manager's telemetryThrough instead of assuming
every batch was taken: when the manager takes part of a backlog, the
rest goes in further requests for as long as each makes progress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alongubkin
alongubkin merged commit ab22b8c into main Oct 5, 2026
21 checks passed
@alongubkin
alongubkin deleted the alon/alien-1219-staging-fixes branch October 5, 2026 01:42
alongubkin added a commit that referenced this pull request Oct 5, 2026
…896)

## Problem
After the recent test fixes, `Rust crates` is ~10.5 min, and the cold
build (~5.3 min) is most of it. Every PR builds and tests all 57
packages, even a change to one crate. Replaying the last 50 merged PRs,
about half affect 11 or fewer packages.

## Change
- **`scripts/affected-rust-packages.py`** reads the PR diff (base..merge
commit) and `cargo metadata`.
- It selects the changed packages plus every package that depends on
them, through normal, dev or build dependencies.
- **Any changed file outside the packages selects the full workspace,**
unless it is documentation (`docs/`, `*.md`). That covers manifests, the
lockfile, toolchain, `.cargo/`, nextest config, workflows, Dockerfiles,
scripts, `examples/` and `packages/`. Unknown inputs always mean "test
everything".
- **Packages under `examples/` and `tests/` are fixtures** that other
packages' tests read (the CLI checks every example's `template.toml`),
so changes there select the full workspace too.
- **A docs-only change selects no packages** (mode `none`), and the Rust
job and check are skipped.
- **`changes` runs it on pull requests** (stable cargo, so the pinned
nightly isn't installed there). Pushes, merge groups and manual runs are
always `full`.
- **`Rust crates` builds and tests that selection** (`$RUST_SELECTION`),
with the CI features limited to the selected packages.
- The privileged sandbox-agent tests run when `alien-sandbox-agent` is
selected.
  - The image contract test runs when `alien-core` is selected.
- The smoke harness runs in full mode, since its inputs are scripts and
Dockerfiles, which always select full.
- **New `Rust check` job,** in parallel and only in affected mode:
`cargo check --workspace --all-targets` with the CI features, so no
package can stop compiling unnoticed. It's added to `All tests passed`.

## Measured (CI benchmark, 2 runs each, `depot-ubuntu-24.04-arm-8`)

| PR shape | Full run today | Affected build + tests | `Rust check`
(parallel) |
|---|---|---|---|
| `alien-cli` only (1 package) | ~310 s build + ~214 s tests | 142 s + 2
s | ~193 s |
| `alien-infra` (8 packages) | same | 194 s + 44 s | ~187 s |
| `alien-core` or `Cargo.lock` (42+) | same | ≈ full | — |

The replays select as expected: #819 (CLI only) gets 1 package, #886
(alien-infra) 8, #865 (core) 42. #880 and #891 changed CI files, so they
get the full run.

This PR changes `ci-fast.yml` and a script, so its own CI takes the full
run.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant