This repository was archived by the owner on Nov 3, 2026. It is now read-only.
Repository navigation
Sync alpha with latest upstream while preserving fork changes - #1
Merged
Merged
Conversation
…nbook docs: add a release-candidate testing runbook
…ollowups fix(certbot): tighten the ACME challenge-domain rule and the paths that report failures
…ack-TEE#1135) * docs: cover gateway clustering and the proxy modes left untested * docs: record what an AMD SEV-SNP run actually requires The last round stopped at an unreachable AMD KDS, so section 9 was written from code reading. A completed run since then turned up four things that cost time and are not visible from the source: - `sev_snp_key_release` defaults off and rejects *after* the quote verifies, so a good quote still yields a reboot loop. Only SEV-SNP and NitroTPM are gated this way; the TDX variants are not, which is why the gate surprises. - Flipping that flag on a bootstrapped KMS destroys it. The local key provider seals to RTMR3, which carries the compose hash. Onboarding a second KMS is the way, and the inherited identity shows up in the CA public key rather than the certificate. - `GetKey`/`Attest` are not on the external listener, and the internal socket mounts without the `/prpc` prefix. - KDS rate limiting returns 429 on repeat verification of the same chip, which reads like a verification failure. Also adds an offline verification row to the section 7 table: capturing an attestation and re-verifying a one-byte-flipped copy is the cheapest way to show the crypto is live, provided the flip lands inside the signed report rather than the CBOR framing. * docs: list the AMD SEV-SNP configuration explicitly The previous revision described `sev_snp_key_release` in prose, which is enough to recognise the failure but not enough to set up a run. Adds a table of every setting an AMD run touches, across vmm.toml and kms.toml, with the default beside it -- including the ones to leave alone, so a reader can tell 'unset is correct' from 'not yet investigated'. The trust-anchor pair is the non-obvious one: setting any `root_ca` path without `insecure_allow_external_trust_anchors` refuses to start rather than falling back, and the same `[core.attestation]` block is shared with dstack-verifier.toml. * docs: say what KDS caching exists, and drop a duplicated paragraph 'Provision the host' is advice that invites the obvious follow-up question -- is there a cache service to run instead? There is not, and the answer is not visible without reading sev-snp-qvl: the only cache is a capacity-bounded in-process moka cache with no TTL and no persistence, so every fresh process starts cold. Worth stating plainly next to the advice, together with the fact that `amd_kds` would accept a mirror if someone wrote one, and that the NVIDIA collateral did get the persistent proxy AMD lacks. Also removes a paragraph the previous commit duplicated when it split the section. * docs: correct the AMD host-certificate advice, which does not work on stock QEMU The previous revision told the reader to provision host certificates with 'snphost / sevctl' and treated the KDS dependency as removable. Checking on the host that ran this round, it is not: - `sev-snp-guest` in QEMU 10.2.1 has no `certs-path` property, and the string is absent from the binary, so there is no way to hand QEMU the GHCB cert blob `snphost import` produces. - `SNP_SET_EXT_CONFIG`, the other staging route, is not in upstream `psp-sev.h`; it was AMD's out-of-tree fork. - The guest half works fine -- `SNP_GET_EXT_REPORT`/`certs_address` are present -- so the guest asks and receives an empty table, which is why every verification in this round went to KDS. Also drops `sevctl` from the recommendation: it manages the pre-SNP SEV platform and its OCA chain, and has nothing to do with SNP endorsement certificates. Pairing it with snphost was a guess presented as instruction. * docs: cut the host-provisioning detour from the AMD section Section 9.4 had grown into a walkthrough of tooling that cannot be used -- snphost subcommands, a QEMU property dump, and an account of why the earlier recommendation was wrong. A runbook is read by someone mid-test; none of that helps them. What is left is the part that changes what a reader does: KDS is a single rate-limited endpoint, its 429 looks like a verification failure, the cache is in-process only, and the host-certificate route is a dead end on a stock QEMU so nobody should spend an afternoon on it. * docs: show that a KDS caching mirror works, with a reference implementation Section 9.4 already said a mirror would drop in behind `amd_kds`. Someone reading that still has to discover the three things that decide whether the proxy is correct, and each was found the hard way: AMD 403s an unexpected Host header, a cached 429 converts a rate limit into an outage, and every KDS response carries `Cache-Control: no-cache` so a plain reverse proxy caches nothing at all. Thirty lines of Worker are cheaper to read than that list in prose. Measured rather than asserted: four cold-process verifications of one real attestation pass through the mirror where the second fails going direct, and a KMS pointed at it released keys to an AMD guest end to end. Also notes why the TTL should be bounded even though a VCEK is valid for seven years -- dstack checks no CRL and no validity dates, so an unbounded cache would freeze that gap rather than merely inherit it.
…keys
`certbot cfg` walks the serialized document and the struct's doc comments in
lockstep, by position. An `Option` that is `None` serializes to nothing, so
`cf_api_url` and `renewed_hook` are absent from the document and every comment
after the first of them describes the key above the one it belongs to:
# Optional Cloudflare-compatible API base URL
dns_txt_ttl = 60
# TTL for DNS TXT challenge records in seconds
auto_set_caa = true
Look the comment up by key name instead. A key with no doc comment keeps none
rather than borrowing its neighbour's.
The CLI keeps the ACME account key and the certificate key in a plain directory on the host that runs it, so nothing about the issuance is attested. A deployed gateway issues its own certificates from the configuration it already holds and publishes the public keys for `ct_monitor` to check. Say so in a README, next to what the subcommands do and where the workdir keeps things. `init`'s help said it initializes the configuration file; it reads the configuration file and creates the ACME account.
Step 4 told the operator to configure `GATEWAY_CERT`/`GATEWAY_KEY` in `build-config.sh` and run `./certbot renew -c certbot.toml` on the host. That is not how a deployed gateway gets a certificate, and `build-config.sh` is not part of this guide's flow: `dstack-gateway` links the `certbot` crate and runs it inside the CVM, answering dns-01 with the DNS credential in its admin config and keeping the ACME account key and every certificate in the CVM's WaveKV store. Following the old text produced a certificate on the host that nothing reads. Describe what step 3 already set up -- `bootstrap-cluster.sh` calling SetCertbotConfig, CreateDnsCredential and AddZtDomain -- how to watch issuance land in `ListZtDomains`, how to pin CAA, and what switching from staging to production takes. Zero-trust HTTPS moves to the required part of the checklist: without a certificate for the domain the gateway cannot serve an app over TLS.
The production setup guide walked the operator through editing `certbot.toml`, running `./certbot set-caa && ./certbot renew` by hand, and pointing `cert_chain`/`cert_key` at the result. A gateway running on the host links the same `certbot` crate as one running in a CVM and issues over dns-01 from its own process, keeping the ACME account key and every certificate in its WaveKV store -- `cert_chain`/`cert_key` only load a certificate something else produced. Configure the gateway instead: the proxy fields, the admin API the ACME settings are stored through, and a `data_dir` that survives restarts so a restart does not ask the CA for a fresh certificate. Then SetCertbotConfig, CreateDnsCredential and AddZtDomain, with what to watch in ListZtDomains, what SetCaa pins, and what switching from staging to production takes. Also: `core.admin.auth_token` is the current key name (`admin_token` is the accepted older one), URL Format becomes its own section rather than sitting inside a configuration step, and the alerting table listed `dstack_gateway_kv_persist_failures_total` twice.
…Dstack-TEE#1142) Co-authored-by: Kevin Wang <fremontkevin@icloud.com>
Bumps [@fastify/static](https://github.com/fastify/fastify-static) to 10.1.3 and updates ancestor dependency [@fastify/swagger-ui](https://github.com/fastify/fastify-swagger-ui). These dependencies need to be updated together. Updates `@fastify/static` from 6.12.0 to 10.1.3 - [Release notes](https://github.com/fastify/fastify-static/releases) - [Commits](fastify/fastify-static@v6.12.0...v10.1.3) Updates `@fastify/swagger-ui` from 2.1.0 to 6.1.1 - [Release notes](https://github.com/fastify/fastify-swagger-ui/releases) - [Commits](fastify/fastify-swagger-ui@v2.1.0...v6.1.1) --- updated-dependencies: - dependency-name: "@fastify/static" dependency-version: 10.1.3 dependency-type: indirect - dependency-name: "@fastify/swagger-ui" dependency-version: 6.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
…nfig fix(certbot): reissue when the configured domains change
…_yarn/dstack/kms/auth-eth/multi-406b073587 build(deps): bump @fastify/static and @fastify/swagger-ui in /dstack/kms/auth-eth
Rotation, CAA reconciliation, and first-use registration all read or re-pin the same account, so they now take the same KV lock. Two consequences. Registration under the lock cannot be reached from inside a region that already holds it: set_caa_all held the in-process caa_lock across its per-domain loop, and a fresh cluster's first SetCaa registers from inside that loop -- which, with a non-reentrant tokio Mutex and no timeout, hung the task and left the lock held for the life of the process. set_caa_all now registers the account before it takes the lock, where the steady state costs one KV read. Dropping caa_lock for the KV lock also widens what is ordered: CAA reconciliation was serialized within a process only, so one node's SetCaa could interleave with another's rotation over the same zone. Reconciling rewrites a zone's issuer records in place -- guard, sweep, write, unguard -- and two runs over one zone delete each other's records, which can leave the ";" guards behind and block issuance until a later run succeeds.
Nothing under the ACME lock may take it again. `set_caa` now loads the stored account instead of registering one, so the locked region cannot reach `acquire_acme_lock` at all -- the caller registers up front, and the property holds by construction rather than by argument. The E2E suite never called SetCaa or RotateAcmeCredentials, so the two admin operations that take the cluster-wide lock ran nowhere outside single-process unit tests. Both nodes now reconcile CAA, then one rotates the shared account and the other issues with it, which is also what proves the switch reached the cluster rather than one process. The zone is read back from the mock provider after each step: exactly one `issue` and one `issuewild` pinned to the same account, no ";" guard left behind -- the state a reconciliation that was interleaved, or that died halfway, does not produce. Admin RPCs are bounded by `--max-time` so an RPC that blocks forever fails the suite where the cause is obvious, instead of hanging it until the job timeout.
The suite was one indivisible run: KMS and Gateway 0.5.8 rolled to current, with two apps. A change confined to one area had to pay for all of it, and one area it could never reach at all -- a fresh cluster's first ACME account registration, because 0.5.8 registers the shared account long before the current binary starts. A phase is now the unit a run can be limited to (`./run-e2e.sh --phase certbot`, or DSTACK_E2E_PHASE). Each is self-contained: it deploys what it needs and asserts on it. The `certbot` phase brings up a current KMS and two current Gateway nodes, then reconciles CAA on a cluster holding no account -- registering one from inside the region that holds the cluster-wide ACME lock -- issues against it, requires the second node to adopt that account rather than register its own, and rotates. Only the upgrade phase boots the v0.5.11 compatibility image, so no other phase requires it to be present, and none widens the authorization allowlist with an OS digest it will never launch. `run-upgrade-e2e.sh` stays as a wrapper.
Two things a current-only cluster hits that an upgraded one never does. `max_dns_wait: 0` is rejected by current code at credential creation -- an issuance that never waits for propagation cannot succeed against a real provider -- and only 0.5.8 ever accepted it. The upgrade phase configures the cluster while the nodes still run 0.5.8, so the value survives into current code as stored state and the validation is never reached. One second is as good as none against a Pebble configured to validate unconditionally. Adding a ZT domain starts an issuance, and on a fresh cluster that issuance registers the shared ACME account -- so an operator's SetCaa, issued right after, races it for the cluster-wide lock and is refused. That refusal is deliberate and says to retry after the holder finishes, which is seconds for a registration. So retry, the way this suite already retries the per-domain certificate lock. Any other error still fails immediately.
…egister-race fix(gateway): register the shared ACME account under the rotation lock
dns-01 rewrites the zone on every order, so certbot holds a DNS provider credential for the life of the deployment. dns-persist-01 (draft-ietf-acme-dns-persist-01) proves control with a `_validation-persist` TXT record published once, out of band: the record names the CA and the ACME account, nothing about it changes between orders, and certbot only ever reads DNS. `ValidationMethod` replaces the `Dns01Client` field on `AcmeClient`, so the dns-01-only state -- the provider client and the TXT TTL -- lives in the one variant that has any use for it, and dns-persist-01 cannot be constructed holding a credential it would never call. `check_dns` widens from an exact match on the key authorization to matching whatever the challenge expects, and the cleanup pass skips records certbot did not create: a persistent record is the operator's and outlives every order. The self-check stays advisory for both methods. Our resolver is not the CA's, and under dns-persist-01 our expectation can be stricter than the CA's -- the challenge's `issuer-domain-names` are not exposed by instant-acme -- so a record we cannot see is named in a warning and the order proceeds. CAA content now names the challenge in use, because a record pinned to `validationmethods=dns-01` refuses every dns-persist-01 order. The dns-01 string is unchanged byte for byte, pinned by a test, so records published by earlier releases keep matching. `required_dns_records` renders the whole one-time setup -- validation record plus CAA -- from an account URI rather than a live client, so a caller holding only stored credentials can render it without a round trip to the CA. The record grammar is an RFC 8659 issue-value, and the parser mirrors what CAs run down to the parts that reject rather than ignore (trailing semicolon, repeated tag, whitespace in a value), so certbot never renders a record the CA would refuse or accepts one it would. The gateway keeps its dns-01 behaviour; the call sites move to the new constructor unchanged.
Under dns-persist-01 certbot cannot write the records it needs, so the records are the setup. `certbot dns-records` prints them as zone-file lines for the configured domains, ready to paste into any provider, once `certbot init` has registered the account they name. `challenge` and `issuer_domain_name` join certbot.toml, and `cf_api_token` becomes optional -- a token left configured alongside dns-persist-01 is warned about rather than silently ignored. `auto_set_caa` is refused outright with dns-persist-01: it promises certbot keeps CAA in sync, and without write access nothing can keep that promise.
A gateway CVM running dns-01 holds a Cloudflare token with write access to the operator's whole zone. Attestation covers what the CVM runs, not what becomes of a secret it holds, so that token is the widest credential in the deployment and it exists only to write one TXT record per order. dns-persist-01 removes it: control comes from a `_validation-persist` record the operator publishes once, and the CVM never gets DNS write access at all. `ZtDomainConfig.challenge` picks the method per domain and defaults to dns-01, so records written before the field existed decode as the method those deployments were using -- pinned by a test over both the named and the legacy positional msgpack encodings. Such a domain needs no DNS credential, and `validation_for` never looks one up for it. `GetZtDomain` and `ListZtDomains` return the records to publish in `required_dns_records`, rendered from the stored account URI with no ACME round trip so the listing endpoints stay cheap; it comes back empty rather than failing when no account exists yet. Two operations cannot be self-service for such a domain, and say so rather than failing silently: - `SetCaa` skips it and logs the records instead. There is nothing to reconcile without write access, and one such domain must not make the RPC unusable for the dns-01 domains beside it; the summary reports how many were left to the operator. - `RotateAcmeCredentials` moves the cluster to a new account while every `_validation-persist` record still names the old one, so orders for those domains fail until the operator republishes. The response now carries the new records in `required_dns_records`, rendered after the switch so they name the account the cluster actually moved to, and `domains_updated` counts only the domains whose CAA was re-pinned.
The mkosi backend still consumes kernel, OVMF and ZFS patches, the initramfs init script, systemd units, the AWS hardening audit and version references from os/yocto/. Saying only "deprecated, will be removed" invites deleting that tree or skipping edits to files that are live inputs of the default image. State the dependency wherever the deprecation is. Also correct statements that no longer hold with mkosi as the default: the source-boundary description (mkosi mounts the whole repository as an ephemeral build source), the AWS runbook's "os/build.sh produces the archive" (a cached native mkosi build skips tarballs), the -o DIR hint that make os-image cannot take, the missing root requirement for native builds, and a leftover "experimental" comment in versions.env.
…_yarn/dstack/kms/auth-eth-bun/hono-4.13.5 build(deps): bump hono from 4.12.34 to 4.13.5 in /dstack/kms/auth-eth-bun
…_yarn/dstack/kms/auth-mock/hono-4.13.5 build(deps): bump hono from 4.12.34 to 4.13.5 in /dstack/kms/auth-mock
…_yarn/dstack/kms/auth-simple/hono-4.13.5 build(deps): bump hono from 4.12.34 to 4.13.5 in /dstack/kms/auth-simple
…_yarn/dstack/kms/auth-mock/vitest-4.1.11 build(deps-dev): bump vitest from 4.1.0 to 4.1.11 in /dstack/kms/auth-mock
…pack feat(guest-agent)!: always encode v1 attestations as msgpack
…-os-backend docs(os): follow-up review fixes for the mkosi default switch
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.26.0 to 7.29.7. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-core) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 7.29.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
The builder images point APT at snapshot.debian.org. When the snapshot service is flaky (e.g. 503 No healthy backends), apt-get update only warns about indexes it failed to fetch and exits 0. If the security index is the one that failed, apt silently installs older versions from the main suite and the build later fails in verify-pinned-packages.sh with a misleading "regenerate pinned packages" diff. Pass -o APT::Update::Error-Mode=any so a failed index fetch aborts the build right away with the real cause.
…_yarn/dstack/kms/auth-eth-bun/vitest-4.1.11 build(deps-dev): bump vitest from 3.2.6 to 4.1.11 in /dstack/kms/auth-eth-bun
Bumps and [minimatch](https://github.com/isaacs/minimatch). These dependencies needed to be updated together. Updates `minimatch` from 3.1.2 to 3.1.5 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](isaacs/minimatch@v3.1.2...v3.1.5) Updates `minimatch` from 5.1.6 to 5.1.9 - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](isaacs/minimatch@v3.1.2...v3.1.5) --- updated-dependencies: - dependency-name: minimatch dependency-version: 3.1.5 dependency-type: indirect - dependency-name: minimatch dependency-version: 5.1.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
…_yarn/dstack/kms/auth-eth/babel/core-7.29.7 build(deps-dev): bump @babel/core from 7.26.0 to 7.29.7 in /dstack/kms/auth-eth
…r-mode build: fail apt-get update on any fetch error in builder images
A bridge NIC used to have two owners: netd built the TAP when libvirt filtering was on or the NIC wanted more than one queue pair, and QEMU's setuid qemu-bridge-helper built it otherwise. Each path answered the data-plane questions differently -- which netdev QEMU gets, whether vhost is really on, whether queues had to be clamped for want of netd -- and the VMM had to probe netd and record which path a NIC took so teardown could undo it. Every bridge NIC now gets a netd-built TAP and `-netdev tap,ifname=`, with vhost and queues applied uniformly: - drop the bridge-helper paths, `cvm.qemu_bridge_helper`, the netd reachability probe, and the no-netd queue clamp - drop the `netd_interface` runtime marker; `remove` no longer carries `filtered` and clears any binding best-effort - one-shot `run` refuses bridge and macvtap outside `--dry-run`, since it does not manage netd interface lifecycle - `is_unreachable` now finds the marker (`chain()` never did), and only ENOENT/ECONNREFUSED count as an absent netd - setup-bridge.sh no longer configures qemu-bridge-helper or bridge.conf
The yocto docker-moby recipe installed a docker.service drop-in that set CPUAffinity=0. dockerd validates --cpus against sched_getaffinity(2), so the pin capped every container at one CPU and made 'docker run --cpus 2' fail with 'Range of CPUs is from 0.01 to 1.00'. Drop the override so containers can use the CPU limits users ask for. The mkosi images never carried this pin, so both OS backends now behave the same. Fixes Dstack-TEE#410
fix(os): stop pinning dockerd to CPU 0 in yocto images
Split out of the vhost/multiqueue change (Dstack-TEE#1145); carries the port mapping parts of Dstack-TEE#1154. `port_map` is implemented as QEMU `hostfwd=` entries, and QEMU attached every one to the first user-mode NIC. With several NICs that choice was made silently, and a VM with no user-mode NIC dropped its mappings with no warning. - `PortMapping.nic_index` in the RPC, `--port ...@<nic>` in vmm-cli.py and dstack-cli, and a NIC column in the UI port editor - an unpinned mapping still goes to the first user-mode NIC - a pin to a NIC the VM does not have, or to a backend that cannot publish a host port (bridge, macvtap, custom), is refused at deployment - a mapping stranded by a later topology change is named in the launch log
…tiqueue feat(vmm): run virtio-net on vhost-net with configurable queue pairs
…_yarn/dstack/kms/auth-eth/multi-acd8535d99 build(deps): bump minimatch in /dstack/kms/auth-eth
Docker Build Check exported each builder stage to the Actions cache with mode=max. The source is cloned at DSTACK_REV inside the build, so the cargo layer misses on every commit, yet the export still uploaded the toolchain and target directory: about 150s of the ~9.5 minute image step in each of the three jobs, and the bulk of the repository's Actions cache usage. The layers it could reuse, the pinned-package install and rustup, take about fifteen seconds. SDK tests cached only the `sdk/rust` workspace, while `sdk/run-tests.sh` first builds the release simulator from `dstack/`. That build ran cold on every run and took 4m36s of a 6m39s job. Add `dstack` to the rust-cache workspaces.
…m pushes only The `docker-container` builder that setup-buildx creates by default exports every `--load` as a tarball and imports it into the daemon. For the `*-builder` targets, which carry the toolchain and the cargo target directory, that took 2-3 minutes per job once the gha layer cache no longer paid the compression cost up front. The daemon's own builder puts the image in the store directly, and the second build of the builder target reuses the first. The SDK cargo cache is about 1 GB. Saving it from every pull request ref fills the 10 GB repository quota and evicts the shared entries, so save it only from pushes and let pull requests restore from the base branch.
…cache ci: speed up Docker Build Check and SDK tests
…ing-nic feat(vmm): allow port mappings to specify a NIC index
…tion
netd accepted a single JSON message per connection, tagged with an
`operation` field and decoded into one `Request` enum, and answered with a
flat response struct whose fields each operation filled in differently.
Define the protocol in `netd_rpc.proto` instead: `PrepareBridge`,
`PrepareMacvtap`, `RemoveInterface` and `CheckInterface` each have their own
request and response messages. netd serves the generated `NetdServer` with
Rocket and ra-rpc on the same Unix socket (bound itself or handed over by
systemd), and the VMM calls it through the generated `NetdClient`. The
hand-written framing, size limits, liveness-probe handling and the tagged
request/response types go away.
Operations still run one at a time: a FIFO async mutex keeps them in arrival
order, which the VMM's rollback after a timed-out Prepare relies on, and the
flock still serializes against other netd processes.
`PrpcClient` now includes the server's `{"error": ...}` message when a call
fails, so netd's reason for refusing a request reaches the VMM log instead of
only a status code.
This is a wire-protocol break: the VMM and netd must come from the same
release, and `dstack-netd` has to be restarted together with the VMM.
refactor(vmm): serve netd as a pRPC service with one method per operation
… support Integrate upstream 0a2f04c. Retain DSTACKS1 per-secret envelopes, GHCR publication, and the Yocto loader fix. Supersede the old no-TEE bypass with upstream development simulator support and fail-closed production paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sync the AlphaCompute
alphabranch with upstreamnextat0a2f04cf88e17dd6094f28d6ef44f3bdf8ceb0f3, integrating 1,569 upstream commits while retaining the fork's history.Preserve the fork's DSTACKS1 independently encrypted environment entries, GHCR key-provider publication, and Yocto loader compatibility fix. Replace the obsolete no-TEE bypasses with upstream's explicit development simulator. Reconcile encryption helpers and retain upstream config verification, runtime-event locking, and LUKS checks. Resolve two test-only Clippy warnings without changing production behavior.
Validation on Linux x86_64 with Rust 1.92, final head
0937e30382e1d1745d02f1b7c6b74147f286273c:cargo test --locked -p dstack-util -p dstack-attest -p nsm-qvl -p nsm-attest: 175 passed, zero failed or ignored.cargo clippy --locked -p dstack-util -p dstack-attest -p nsm-qvl -p nsm-attest --all-targets -- -D warnings: passed.cargo fmt --manifest-path dstack/Cargo.toml --all -- --check: passed.python3 -m unittest discover -s dstack/build/shared/tests -v: six passed on Linux.git diff --check upstream/next HEAD: passed; both original fork and upstream heads are ancestors.This PR synchronizes source. Hardware enclave deployment, real provider requests, persistent state, authenticated ingress, and phone pairing remain separate acceptance work under elizaOS/eliza#31328. NSM fixture tests do not establish live enclave attestation.