182 Commits
Author SHA1 Message Date
shrutiyam-glitch 5f64ba4c26 feat(atenet): graceful termination of atenet-router (#774)
### Which issue(s) this PR is related to:
Fixes #721
Required for System Upgrade flow (#473)

### What this PR does / why we need it:
This PR implements graceful termination and zero-outage rolling updates
for `atenet-router` , building on the readiness probe and graceful drain
patterns established in #719 (`atelet`).

Draining a two-container networking pod (`atenet-router` Go
control-plane + `envoy` C++ proxy dataplane) introduces complex
lifecycle interdependencies. This PR resolves the dual-container SIGTERM
race, respects Envoy's `failClosed` `ext_proc` filter dependency,
preserves parked requests riding out worker pool saturation, and
accelerates idle deployments via an event-driven file handshake.

#### 1. Event-Driven Dataplane Synchronization (`emptyDir` Marker File)
Envoy fast-exits by default on SIGTERM. To keep Envoy alive while the Go
control-plane orchestrates the drain, we configured an IPC handshake
between containers via a pod-shared `emptyDir` volume mounted at
`/var/run/atenet`:

* **Go Router Container:** Removes any stale marker at startup, then
writes `/var/run/atenet/drain-complete` when its shutdown sequence
finishes.
* **Envoy Container `preStop` Hook:** Runs `while [ ! -f
/var/run/atenet/drain-complete ]; do sleep 0.5; done`.

**Outcome:** Envoy exits as soon as — the drain is done, rather than
wasting time in a fixed worst-case sleep. If the router crashes, Kubelet
terminates the `preStop` hook at `terminationGracePeriodSeconds:
60`—slower cleanup, never a wedge.

#### 2. The Multi-Container Shutdown Sequence (`drain.go`)
Because Kubernetes issues SIGTERM to both containers at once, a
coordination state machine ensures Envoy never drops a connection and
`ext_proc` is never stopped prematurely:

| Phase / (best-case ex.) Timeline | atenet-router | envoy | K8s /
Service Status |
| :--- | :--- | :--- | :--- |
| **SIGTERM Sent**<br>($t=0\text{s}$) | Catches SIGTERM<br>• Flips
`/readyz` $\rightarrow$ `503`.<br>• Starts 13s `drain-delay`. | Enters
`lifecycle.preStop` hook:<br>`while [ ! -f .../drain-complete ]; do
sleep 0.5; done`<br>• Kubelet holds SIGTERM back. | Deployment will
recreate the pod.<br>EndpointSlice controller begins dropping Old Pod
IP. |
| **Propagation**<br>($t=0\text{s}$ – $t=13\text{s}$) | Keeps serving
normally.<br>• `ext_proc` continues unparking/routing requests. | Runs
normally inside `preStop` loop.<br>• Serves active TCP connections. |
Service endpoint removal completes.<br>No new connections arrive at Old
Pod. |
| **Envoy drain**<br>($t=13\text{s}$) | Issues Envoy admin API
calls:<br>• `/healthcheck/fail`<br>•
`/drain_listeners?graceful&skip_exit`<br>• Polls `/stats` for active
downstream connections. | Begins graceful listener drain:<br>• GOAWAY /
`Connection: close` on established connections.<br>• In-flight requests
keep running. | In-flight HTTP requests finish executing through Envoy.
|
| **ext_proc drain**<br>($t\approx18\text{s}$) | Active Envoy
connections hit 0 (the poll exits early).<br>• Calls
`extproc.GracefulStop()`.<br>• Parked request streams finish. | All
downstream connections closed.<br>• Still waiting in the `preStop` loop.
| All client HTTP responses delivered. |
| **Handshake & Exit**<br>($t=18.5\text{s}$)| `ext_proc` drain
finishes.<br>• Writes `drain-complete` marker.<br>• Hard-stops xDS
(`Stop()`) & exits. | `preStop` loop detects marker file!<br>• `preStop`
exits 0.<br>• Kubelet sends SIGTERM to Envoy.<br>• Envoy exits
immediately. | Old Pod deleted cleanly at ~18.5s (well under the 60s
budget). |

Envoy ref:
https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/draining

#### Testing & Verification

1. Unit Tests (`drain_test.go`): Added comprehensive unit tests
covering:
- Graceful completion of in-flight `ext_proc` streams within deadline.
- Force-stopping straggler streams past `--drain-timeout`.
- Envoy admin API interaction and connection polling.
- Stale marker cleanup and marker file creation.

2. Local testing on kind cluster (Observations):
Test script: `hack/verify-atenet-drain.sh`
- Steady state: `/readyz=200`, `/healthz=200`; the instant the pod
turned Terminating: `/readyz=503` while `/healthz=200` — `NotReady` but
alive, for the whole drain.
- The parked request survived the shutdown: fired at a busy 1-worker
pool → parked → pod deleted while parked → worker freed → HTTP=200,
total=1.89s, body hello from: 169.254.17.2 | preserved memory count: 1 |
preserved file counter: 1 — park → resume → route, served by the
Terminating pod during its drain-delay window.
- Pod terminated 14s after deletion — the idle floor, confirmed across
three runs: >13s drain-delay (sequence ran), ≪60s grace (marker
handshake released Envoy's preStop; no `SIGKILL`).
- Log sequence captured verbatim, drain-delay honored to the millisecond
(17:34:41.706 → 17:34:54.707):
  >Shutdown signal received; draining
  >(+13.000s) Draining Envoy  {window: 15s}
  >Envoy drained
  >Starting ext_proc drain
  >ext_proc drain completed within deadline
  >Drain-complete marker written  {path: /var/run/atenet/drain-complete}
  >Shutdown complete


- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-08-07 13:36:08 -07:00
Haven Xia 3d33153239 Make envtest offline-capable and factor out TestMain boilerplate (#792)
`setup-envtest use` with no version re-resolves "latest" against the
remote release index on every run, so the envtest-backed packages needed
network even with fully cached binaries.

This PR pins the control plane to `1.36.x`, and fold the three
per-package `envtest` into `internal/testenv.Start`, which also honors
`-short`: `go test -short ./...` skips the envtest-backed packages and
is the guaranteed-offline path.

Have Claude to help me fix it

Fixes #789

- [ ] Tests pass
- [ ] Appropriate changes to documentation are included in the PR
2026-08-07 12:07:31 -07:00
Max Smythe 4ec2bab26b Enable MicroVM Benchmarking (#691)
Currently we are unable to easily automate the benchmarking of micro
VMs.

This PR:

* Refactors the microVM setup scripts to allow discrete installation of
uVM sanbox configs separate from counter demo
* Pipes a MicroVM container test  config through the benchmarking system
* Updates default atelet daemonset to tolerate all kinds of sandboxClass
taints
2026-08-07 11:47:37 -07:00
Elijah Rodriguez-Beltran 8f4c00169d Add e2e test for multi CSI volume actor 2026-08-07 18:20:22 +00:00
Elijah Rodriguez-Beltran 8152de17df Integrate with substrate
CONV=a6947013-0eab-49f2-9960-11d98ee43dbf
2026-08-07 18:20:22 +00:00
Da Huang 7a9bb4b1f2 manifests: centralize the OTLP endpoint in an ate-otel-config ConfigMap (#746)
OTEL_EXPORTER_OTLP_ENDPOINT is written in 9 places: hardcoded inline in
4 base workload manifests, then re-patched in 5 spots across the kind
overlays. Changing the collector address means editing all 9 and knowing
which install path renders which.

Replace them with one checked-in ConfigMap per environment, consumed by
every component via envFrom:

  manifests/ate-install/ate-otel-config.yaml       (GKE)
  manifests/ate-install/kind/ate-otel-config.yaml  (kind, same name)

The GKE copy is listed in manifests/ate-install/base, so token-client,
agentgateway and agentgateway-token-client all inherit it; the kind
overlay lists its own copy of the same ConfigMap name. No overlay builds
on both, so the two never collide.

A kustomize-only fix does not work here. The GKE path applies the base
directory raw and hack/install-ate.sh's targeted redeploys apply single
files with no Kustomize, so the mechanism has to survive `kubectl apply
-f <one-file>` -- which rules out configMapGenerator (hash-suffixed
names) and replacements. envFrom on a stable name reaches every path.

deploy_ate_system applies the ConfigMap before the rendered bundle, the
same way it already applies the namespace. A container whose envFrom
target is missing does not start, and a raw directory apply is ordered
by filename, so ate-api-server.yaml and ate-controller.yaml would
otherwise be created first and sit in CreateContainerConfigError until
the ConfigMap caught up.

This also fixes a latent bug in the targeted redeploys.
deploy_ate_apiserver, deploy_atelet and deploy_atenet apply raw files
even in kind mode, silently reverting the endpoint to the GKE value.
They now apply the environment's ConfigMap via a new apply_otel_config
helper, which picks the file by ATE_INSTALL_KIND rather than applying
the base copy unconditionally -- applying the base one on kind would
break telemetry for every component at once.

atenet-router needs no special handling: since a98f85b1 its
--otlp-collector-address defaults to $OTEL_EXPORTER_OTLP_ENDPOINT, so
Envoy's own spans follow the ConfigMap along with everything else.

OTEL_TRACES_SAMPLER deliberately stays an inline kind patch on
ate-api-server rather than moving into the ConfigMap. The ConfigMap is
shared by every component via envFrom, so putting parentbased_always_on
there would pin the router and the rest of the control plane to 100% and
undo the per-component ratios from 15eecd02.

Note that a ConfigMap edit does not roll the consuming pods the way an
inline env change did, since the pod template is unchanged. Callers must
follow a change with `kubectl rollout restart`. This is documented in
both ConfigMaps, in docs/observability.md, and in the tracing best
practices, which previously told authors to hardcode the variable.

Fixes #745

> It's a good idea to open an issue first for discussion.

- [ ] Tests pass
- [ ] Appropriate changes to documentation are included in the PR
2026-08-05 14:03:41 -04:00
NekoPunch 62a740a4be install: always re-apply CRDs and RBAC on --deploy-ate-system (#698)
Fixes #697

## Summary

`deploy_ate_system` gated `manifests/ate-install/generated/` behind
`ensure_crds`, whose existence check skips the directory on any upgrade
— stranding CRD schemas and, since `role.yaml` has no other apply path,
all ClusterRoles at first-install state. A controller image needing a
new permission then deadlocks on informer start while the rollout
reports success.

`deploy_ate_system` now calls `deploy_crds` unconditionally (`kubectl
apply` is idempotent). The demo scripts and per-component deploy flags
keep `ensure_crds`, where "make sure they exist" is the intended
semantic.

## Test plan

- Reproduced on a 4-day-old kind cluster: upgrading the control plane
deadlocked ate-controller on `cannot list networkpolicies`; manually
applying `role.yaml` unblocked it.
- With this fix, the same `install-ate-kind.sh --deploy-ate-system` run
prints the `deploy_crds` step and re-applied the drifted manifests
(`actortemplates.ate.dev configured`, `workerpools.ate.dev configured`,
ClusterRoles applied); cluster reconciles normally.
- `bash -n hack/install-ate.sh`.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR (none
needed)
2026-08-03 22:55:30 -07:00
John Howard 6987214b8f Address review comments 2026-08-03 14:23:16 -07:00
John Howard 9e74b1d729 atenet: add option to run agentgateway
Agentgateway is a popular [AAIF](https://aaif.io/) project designed for
agentic systems. It is of particular interest for substrate users as it
was designed specifically to serve the role of an egress proxy for
agents and other AI-adjacent workloads, with strong support for
credential injection, token exchanges, TLS MITM, and other
authentication and authorization schemes.

Agentgateway supports the ext_proc protocol, like Envoy, so we use that
here. There has been some debate in the community around the long term
end state of ext_proc vs other options, but for now this maintains the
status quo.

While Agentgateway can be configured dynamically over XDS, it does not
take the same configuration as Envoy. However, none of the config is
dynamic anyways, so we use just a static configuration file (configmap)
for now to keep things simple.

While we don't have specific per-component/file OWNERS in the project at
the moment, I can informally commit to myself and Eitan maintaining this
integration. Given the goals around velocity in the project we can
commit to either rapidly fixing any issues that may arise or
removing/disabling the integration if this ends up slowing things down.
2026-08-03 14:23:16 -07:00
Benjamin Elder e4844d0fd2 e2e,ci: keep a failed run's namespaces and dump their worker logs (#654)
When an e2e test failed, the evidence was deleted before anyone could
read it. The suite deleted every namespace it created on the way out,
taking the worker pods with it, and the workflow's post-failure dump
only looked at three fixed namespaces — never the suites' randomly-named
ones. So a failure inside an actor (#619: a micro-VM resume where the
guest died at boot) left nothing behind but the RPC error the test
printed.

Keep the namespaces when the suite failed, and dump every worker pod in
every namespace, so the ateom logs — which carry the guest's console
tail — reach the failed run's output.

Kept namespaces are nobody's to reclaim, and each holds a WorkerPool's
worth of running pods, so they now carry an ate.dev/e2e label and
hack/cleanup-e2e.sh deletes them once the logs have served their
purpose. CI throws its cluster away, but a development cluster
accumulates them run after run.

Fixes #<issue_number_goes_here>

Built while debugging
https://github.com/agent-substrate/substrate/issues/619

> It's a good idea to open an issue first for discussion.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-30 21:00:19 -07:00
Lior Lieberman 92f1aa7276 Rename SessionIdentity to ActorIdentity
Sessions are no longer a concept in Substrate; Actor is the glossary
term. This completes the "s/Session/Actor" TODO that sat at the top of
ateapi.proto, and removes the TODO.

API surface:
  service SessionIdentity        -> ActorIdentity
  MintJWTRequest.session_id      -> actor_id
  MintJWTResponse.session_jwt    -> actor_jwt
  MintCertRequest.session_id     -> actor_id
  MintCertResponse.session_certificates -> actor_certificates

Go packages:
  cmd/ateapi/internal/sessionidentity -> actoridentity
  cmd/ateapi/internal/sessionidjwt    -> actoridjwt

Flags and cluster resources:
  --session-id-jwt-pool -> --actor-id-jwt-pool
  --session-id-ca-pool  -> --actor-id-ca-pool
  Secrets, volumes and mount paths renamed to match, in both
  manifests/ate-install/ate-api-server.yaml and hack/install-ate.sh
  (--create-session-id-ca-pool-secret -> --create-actor-id-ca-pool-secret).

Two credential identity values change with the rename:
  JWT issuer https://broker.agentic-substrate-session-id-broker.svc
          -> https://broker.agentic-substrate-actor-id-broker.svc
  SPIFFE ID spiffe://substrate-session.local/app/../session/..
          -> spiffe://substrate-actor.local/app/../actor/..
Tokens and certificates issued before this change will not validate
against the new issuer or trust domain.

BREAKING: the gRPC wire path moves from /ateapi.SessionIdentity/* to
/ateapi.ActorIdentity/*, and the Secrets must be recreated under their
new names before the new ate-api-server rolls out.
2026-07-30 07:34:29 -07:00
Luiz Oliveira 9490650566 Add autoscaled-workerpool demo using HPA and prometheus-adapter on Kind (#576)
This introduces a new demo (`demos/autoscaled-workerpool`) demonstrating
how to dynamically autoscale a WorkerPool using HPA +
`prometheus-adapter` on a local Kind cluster.

As mentioned in https://github.com/agent-substrate/substrate/issues/198,
this approach may be too slow for some use cases, but this is a good
first milestone.

Plus, there are some limitations with scaling workerpools that still
need to be addressed, for example:

- Scale-down can strand paused actors. When a worker pod is removed, a
local-snapshot paused actor keeps its node pin pointing at a node that
may no longer have (free) worker pods.
- Scale-up gives no locality guarantee: If there are multiple
local-snapshot paused actors that can't resume because no worker pods
are available on their node, upscaling will not unblock them: the added
capacity can land anywhere, so the pool can grow without ever placing a
worker where a stranded actor needs it.
- Scale-down picks victims blind to actor assignment (can kill busy
pods).

- [x] Tests pass: n/a
- [x] Appropriate changes to documentation are included in the PR
2026-07-29 14:48:22 -04:00
Haven Xia dc88f9a32f Fix the issue that run-e2e.sh doesn't work on bash 3.2 macos. (#571)
run-e2e.sh always fail on my mac with ` line 106: go_test_args[@]:
unbound variable,exit`, asked Claude code and fix related Bash 3.2
problem in scripts.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-29 14:04:59 -04:00
Omer Yahud 8f64f67f82 Add request-parking demo
An oversubscribed WorkerPool (2 workers, several actors) that exercises the router parking path: requests to a saturated pool park and retry instead of failing fast, and are served once capacity frees up. Includes load.sh and --deploy-demo-parking / --delete-demo-parking wiring in hack/install-ate.sh.
2026-07-28 23:55:51 -07:00
Julian Gutierrez Oschmann 40da2c9a96 Prefactoring: Delete agent-secret demo.
This demo is broken now that we require authn to ate-apiserver. The
fix is not trivial as it requires the actor to be able to authenticate, plus
it doesn't really adds much.
2026-07-28 08:27:13 -07:00
Chuang Wang 474f3d2252 Wait on the correct Deployment name when deploying atenet-dns (#542)
The Deployment in `atenet-dns.yaml` is named `dns`; every other resource
in that file is `atenet-dns`. The installer waited on the filename
rather than the actual Deployment, so this step failed with NotFound on
every otherwise-successful deploy.
2026-07-27 12:04:08 -04:00
Zoe Zhao 9890219151 Added mTLS between ate system components (#237)
Part of [#170](https://github.com/agent-substrate/substrate/issues/170)
Establishes mutual TLS between all ate system components, and updates
the certificate plumbing it depends on.

Main changes:
1. The atenet router now verifies ate apiserver' serving certificate,
and presents its client cert to ate apiserver. Previously the connection
used `InsecureSkipVerify`.
2. AteApi server verifies atelet's serving cert.

Minor bug fixes:
1. Prevent `servicednssigner` from signing a cert with no DNS SANs. Also
updated valkey cluster's cert configuration, because it was relying on
the cert with empty DNS.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-24 15:43:03 -07:00
Michelle Au 9300387fef Add basic per-actor external volume flow (#405)
Initial part of #232.

Extends the ActorTemplate API to add support for per-actor external
volumes and adds control plane and atelet hooks following the Actor
lifecycle.

Callouts to volume operations are abstracted with a Volume interface.
Right now, only a mock volume plugin for testing has been implemented,
but we will add CSI support next.

- [x] Tests pass
- [ ] Appropriate changes to documentation are included in the PR - Not
going to update documentation until we add CSI support.
2026-07-24 14:40:26 -07:00
Haven Xia 5f6f14c5c8 Generalize rootful test execution via internal/roottest discovery (#507)
Fix #501

Tests that need root (overlay mounts, mknod, `trusted.*` xattrs, ...)
call `roottest.Require(t, ...)` from
[internal/roottest](internal/roottest) as their first statement. They
skip in a plain `go test ./...`; CI reruns every package whose tests
import that package under `sudo`.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-23 18:39:39 -07:00
Benjamin Elder f7f8727ae8 microvm: bump runtime assets to kata 4.0.0 + virtiofsd v1.14.0 (#506)
- We no longer need to compile virtiofsd when installing for amd64, we
still need to for arm64 (no upstream release)
- Drop-in compatible, only updating the scripts that manage obtaining
the binaries, and the versions / hashes in the config.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-23 18:45:08 -04:00
dependabot[bot] 9e2a669e33 build(deps): bump google.golang.org/grpc from 1.81.1 to 1.82.1 in /hack/tools/ko (#497)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from
1.81.1 to 1.82.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.82.1</h2>
<h1>Security</h1>
<ul>
<li>server: Stop reading from the connection when flooded by HTTP/2
frames. The default value for this limit is 100 frames, excluding DATA
and HEADERS, and may be changed by setting environment variable
<code>GRPC_GO_EXPERIMENTAL_CONTROL_BUFFER_THROTTLE_LIMIT</code>.</li>
<li>xds/rbac: Support <code>Metadata</code> and
<code>RequestedServerName</code> permissions matcher fields. If present
in a DENY rule, previously these would be ignored and fail-open.</li>
<li>xds/rbac: Fix panic when parsing unsupported fields in
<code>NotRule</code>/<code>NotId</code> permissions.</li>
<li>xds/rbac: Support the deprecated <code>source_ip</code> principal
identifier by treating it as equivalent to
<code>direct_remote_ip</code>.</li>
</ul>
<h2>Release 1.82.0</h2>
<h1>Behavior Changes</h1>
<ul>
<li>server: Remove support for
<code>GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING</code>
environment varibale. Strict incoming RPC path validation (which has
been the default since <code>v1.79.3</code>) can no longer be disabled.
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/9112">#9112</a>)</li>
<li>transport: Add environment variable to change the default max header
list size from <code>16MB</code> to <code>8KB</code>. This may be
enabled by setting
<code>GRPC_GO_EXPERIMENTAL_ENABLE_8KB_DEFAULT_HEADER_LIST_SIZE=true</code>.
This will be enabled by default in a subsequent release. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9019">#9019</a>)</li>
<li>balancer: Load Balancing policy registry is now case-sensitive. Set
<code>GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES=false</code>
(and file an issue) to revert to case-insensitive behavior. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9017">#9017</a>)</li>
</ul>
<h1>New Features</h1>
<ul>
<li>experimental/stats: Expose a new API,
<code>NewContextWithLabelCallback</code>, to register a callback that is
invoked when telemetry labels are added. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8877">#8877</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/seth-epps"><code>@​seth-epps</code></a></li>
</ul>
</li>
<li>client: Return a portion of the response body in the error message,
when the client receives an unexpected non-gRPC HTTP response, to make
debugging easier. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8929">#8929</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/chengxilo"><code>@​chengxilo</code></a></li>
</ul>
</li>
<li>server: Add environment variable
<code>GRPC_GO_SERVER_GOROUTINE_LABELS</code> that controls setting
<code>runtime/pprof.Labels</code> on goroutines spawned by the server.
Set <code>GRPC_GO_SERVER_GOROUTINE_LABELS=grpc.method=true</code> to add
the <code>grpc.method</code> label on goroutines spawned to handle
incoming requests. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9082">#9082</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/dfinkel"><code>@​dfinkel</code></a></li>
</ul>
</li>
</ul>
<h1>Bug Fixes</h1>
<ul>
<li>xds/server: Fix a memory leak of HTTP filter instances occurring
when route configurations are updated in-place during a Route Discovery
Service (RDS) update. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9138">#9138</a>)</li>
<li>grpc: In the deprecated <code>gzip</code> Compressor (used via the
deprecated <code>WithCompressor</code> dial option), enforce the
<code>MaxRecvMsgSize</code> limit on the decompressed message buffer,
preventing excessive memory allocation from highly compressed payloads.
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/9114">#9114</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/evilgensec"><code>@​evilgensec</code></a></li>
</ul>
</li>
<li>stats/opentelemetry: Record retry attempts,
<code>grpc.previous-rpc-attempts</code>, at the call level and not the
attempt level. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8923">#8923</a>)</li>
<li>encoding: Ensure <code>Close()</code> is always called on readers
returned from <code>Compressor.Decompress</code> if possible. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9135">#9135</a>)</li>
<li>channelz: Fix the <code>LastMessageSentTimestamp</code> and
<code>LastMessageReceivedTimestamp</code> fields in
<code>SocketMetrics</code> to ensure they contain correct timestamp
values. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9109">#9109</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/grpc/grpc-go/commit/ebd8f06a09426fbece97157c95c3917abff28f4e"><code>ebd8f06</code></a>
Change version to 1.82.1 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9238">#9238</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/4ea465d4ab98013f72a142fe0fc89c19770b2935"><code>4ea465d</code></a>
Cherry-pick commits (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9236">#9236</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/9494a2cf32a0ec9d35420af401445ef3c9f66f05"><code>9494a2c</code></a>
Change version to 1.82.1-dev (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9171">#9171</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/bd239854f0ab7f1ee63457d47f7c1d2675e1f736"><code>bd23985</code></a>
Change version to 1.82.0 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9170">#9170</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/0f3086db7a755b6af83a90809471dd7f645b345a"><code>0f3086d</code></a>
Fix minor issues not covered by PR <a
href="https://redirect.github.com/grpc/grpc-go/issues/9137">#9137</a>
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/9147">#9147</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/fef07fbb2b94b668e8daca1f6b70433dcd36c1c8"><code>fef07fb</code></a>
internal: Split v3procservicepb import into pb and grpc for extproc (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9163">#9163</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/91dd64f4b83cb5134e279d1126ebb1ccf47d4d31"><code>91dd64f</code></a>
transport: surface subsequent data when receiving non-gRPC header (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8929">#8929</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/adc97de9521a9f377dab5e911039842dc4de23e5"><code>adc97de</code></a>
test/kokoro: add config for regional-td test (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9158">#9158</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/57c9ff14e05b535ee6995ba49bc882b287a175de"><code>57c9ff1</code></a>
xds: ensure full-string matching for RBAC Filter rules (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9148">#9148</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/b58f32d9ff07c612d64e677bd826bcbec88af9bd"><code>b58f32d</code></a>
server: Set a pprof label on new stream goroutines (<a
href="https://redirect.github.com/grpc/grpc-go/issues/9082">#9082</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/grpc/grpc-go/compare/v1.81.1...v1.82.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.81.1&new-version=1.82.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agent-substrate/substrate/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-22 18:42:56 -04:00
Jaana Dogan 45f20f6571 Remove the Bash 4 requirement (#486)
On macOS, bash default has Bash 3.2 compatibility. mapfile isn't
available and the mapfile command is breaking the install-ate.sh. Use a
while loop to implement the exact behavior.
2026-07-21 20:54:24 -04:00
Julian Gutierrez Oschmann a2d55e99e0 Update Actor ID -> Actor Name references (#455)
Update all old references to actor id to refer to actor name.

Also fix benchmarking framework to use the latest version of the API.
2026-07-17 16:49:19 -07:00
John Howard a814761b6a Avoid redundant object naming suffixes (#441)
Best practices is not to put a -deployment deployment, -role role, etc;
the kind already declares the kind we don't need it in the name as well.
Additionally we did not do it consistently anyways.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-15 16:31:06 -07:00
Luiz Oliveira c1bd202dab fix(scripts): correct jq JSON path selector in delete_demo_actors
Update the actor listing query in `hack/install-ate.sh` to extract `metadata.atespace` and `metadata.name` instead of the legacy root fields `atespace` and `actorId`.

`metadata` was introduced in https://github.com/agent-substrate/substrate/commit/af1f00522c63d24efed30ecb691676ce6fde847a
2026-07-15 14:23:05 -07:00
Tim Hockin 5ea52d90c3 Add {update/verify}/proto-fmt.sh via clang-format
Next commit runs the tool.
2026-07-10 11:23:14 -04:00
dependabot[bot] d858ef8013 build(deps): bump golang.org/x/net in /hack/tools/go-licenses
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.43.0 to 0.55.0.
- [Commits](https://github.com/golang/net/compare/v0.43.0...v0.55.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.55.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-08 16:43:23 -07:00
haoqixu a813175b56 fix InvalidImageName in claude code multiplex demo 2026-07-08 16:42:11 -07:00
Tim Hockin fd353e5662 Set version via ldflags in ko 2026-07-08 13:26:26 -07:00
Tim Hockin b3e7b5bdf1 Bump ko version 2026-07-08 13:26:26 -07:00
dependabot[bot] e43d99bb9a build(deps): bump golang.org/x/crypto in /hack/tools/ko
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.51.0 to 0.52.0.
- [Commits](https://github.com/golang/crypto/compare/v0.51.0...v0.52.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.52.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-08 12:55:03 -07:00
dependabot[bot] 59d89fea60 build(deps): bump github.com/sigstore/timestamp-authority/v2 from 2.0.6 to 2.1.0 in /hack/tools/ko (#366)
Bumps
[github.com/sigstore/timestamp-authority/v2](https://github.com/sigstore/timestamp-authority)
from 2.0.6 to 2.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sigstore/timestamp-authority/releases">github.com/sigstore/timestamp-authority/v2's
releases</a>.</em></p>
<blockquote>
<h2>v2.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bound path and HTTP method metric label cardinality to prevent OOM
in <a
href="https://redirect.github.com/sigstore/timestamp-authority/pull/1374">sigstore/timestamp-authority#1374</a></li>
<li>Fix spec violations in policy, EKU, and hash verification in <a
href="https://redirect.github.com/sigstore/timestamp-authority/pull/1375">sigstore/timestamp-authority#1375</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sigstore/timestamp-authority/compare/v2.0.6...v2.1.0">https://github.com/sigstore/timestamp-authority/compare/v2.0.6...v2.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/58ae149676e193d2dd7e7ee53f231b83fdd10fad"><code>58ae149</code></a>
Fix spec violations in policy, EKU, and hash verification (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1375">#1375</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/506ec57b6ac2ea1e4739322e47453469425b69b5"><code>506ec57</code></a>
Bound path and HTTP method metric label cardinality to prevent OOM (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1374">#1374</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/ee10addd351dc6ee98cce8ff8fd371d7c46da954"><code>ee10add</code></a>
chore(deps): bump the actions group with 2 updates (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1370">#1370</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/5238ec7a129fdb30696877cc72566273b5cda5ed"><code>5238ec7</code></a>
chore(deps): bump golang.org/x/net from 0.54.0 to 0.55.0 (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1369">#1369</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/0ff73b8db18044af0cc8e1ae7e0745fe322377e1"><code>0ff73b8</code></a>
chore(deps): bump goreleaser/goreleaser-action in the actions group (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1367">#1367</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/97813ca20ffde2ee48100f276de8b63a6aabcaf1"><code>97813ca</code></a>
chore(deps): bump the actions group with 2 updates (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1366">#1366</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/ece88f8b7ed97d7018a26e393044de2b8301ab2e"><code>ece88f8</code></a>
chore(deps): bump github.com/go-openapi/runtime from 0.30.0 to 0.31.0
(<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1365">#1365</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/77e0ee5cddc2629879814cff1eedce8eae716a0d"><code>77e0ee5</code></a>
chore(deps): bump github.com/tink-crypto/tink-go-awskms/v2 to v3 (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1364">#1364</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/6ea07dfd04b97429be00e98360b819b277398843"><code>6ea07df</code></a>
chore(deps): bump go.step.sm/crypto from 0.80.0 to 0.81.0 (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1363">#1363</a>)</li>
<li><a
href="https://github.com/sigstore/timestamp-authority/commit/f1dc03b146f2e1ea2c668a8f5849456e7cf0bc5a"><code>f1dc03b</code></a>
chore(deps): bump github.com/tink-crypto/tink-go-hcvault/v2 (<a
href="https://redirect.github.com/sigstore/timestamp-authority/issues/1362">#1362</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/sigstore/timestamp-authority/compare/v2.0.6...v2.1.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/sigstore/timestamp-authority/v2&package-manager=go_modules&previous-version=2.0.6&new-version=2.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agent-substrate/substrate/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 02:00:25 -07:00
dependabot[bot] 4f29aaf321 build(deps): bump golang.org/x/net in /hack/tools/controller-gen
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.48.0 to 0.55.0.
- [Commits](https://github.com/golang/net/compare/v0.48.0...v0.55.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.55.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-07 10:23:52 -07:00
Haven Xia 7f87f0c1e1 Update README.md and scripts to adopt atespaces for existing demos. (#355)
Update README.md and scripts to adopt atespaces for existing demos.

It's intentional to let user choose atespace in demos since actors are
also created by them.


- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-07-06 13:27:38 -04:00
8631ae3465 Add initial threat model for substrate (#303)
This adds an initial threat model for Substrate. The threat model was
originally authored in this Google Doc and shared on the mailing list.

-
https://docs.google.com/document/d/1UAuJzfgkXe6Qa9TTp4wwG0zuHFIGIxEXqafveGq8f9s/edit?resourcekey=0-J-c0L_AJFNjXBX_8TjMbMA&tab=t.0#heading=h.j4pfitmou99h
- https://groups.google.com/g/ate-dev/c/xEPg4RKv-Uk/m/hMoatPvEAAAJ

Note that access to the doc is gated by mailing list membership, you
must join the list to view it and and individual access requests can't
be granted due to a policy restriction. But please comment on this PR at
this point if you have feedback :).

---------

Co-authored-by: Vikas Kumar <skvikas@google.com>
Co-authored-by: Oleg Mitrofanov <gooleg@google.com>
2026-07-01 10:31:39 -07:00
Max Smythe 86e138f628 Activate python virtual environments for scripts that operate within them (#364)
This makes sure the environment is more insulated from idiosyncratic
local machine configurations.
2026-06-30 17:22:15 -07:00
Eitan Yarmush 3400f7fb82 feat: add jwt authentication mode for ateapi (#248)
## Description

  Closes agent-substrate/substrate#222.

Adds a portable JWT authentication path for ateapi clients while keeping
the
  existing mTLS mode as the default.

  ### What changed

  - Added `internal/ateapiauth` with:
    - `mtls` and `jwt` auth modes
    - server-side JWT gRPC interceptors
    - client-side dial options for projected ServiceAccount tokens
  - Wired JWT auth into:
    - `ate-api-server`
    - `ate-controller`
    - `atenet router`
    - `kubectl-ate` port-forward client path
- Updated Kubernetes JWT verification to support custom HTTP clients for
  OIDC/JWKS discovery.
  - Added JWT install overlays:
    - `manifests/ate-install/jwt`
    - `manifests/ate-install/kind-jwt`
  - Updated `hack/install-ate.sh` to opt into JWT mode with:
    - `ATE_API_AUTH_MODE=jwt`
    - `--auth-mode=jwt`

  ### Notes

- Default install behavior remains `mtls`. I think this deserves a
second look as JWT will support more clusters.
- The JWT overlay projects short-lived ServiceAccount tokens with
audience
`api.ate-system.svc` and mounts the service-DNS trust bundle for ateapi
TLS
  verification.
- The current discovery mechanism for JWT mode involves reading the
deployment which I really don't like, but we don't have a "config file"
concept so that bit is a massive TODO.

  ### Validation

```bash
KIND_CLUSTER_NAME=substrate-jwt ./hack/create-kind-cluster.sh

KO_DOCKER_REPO=localhost:5001 \
ATE_INSTALL_KIND=true \
./hack/install-ate.sh --auth-mode=jwt --deploy-ate-system

Validation results:

kubectl config current-context
# kind-substrate-jwt

kubectl get pods -n ate-system
# all runtime pods Running; init jobs Completed

go run ./cmd/kubectl-ate --context kind-substrate-jwt get actors
# succeeded, empty actor list
```
2026-06-30 17:20:56 -07:00
Zoe Zhao 680dbea475 Update default GKE cluster version and enable Managed OTel feature (#352)
1) Always create a cluster with GKE Managed OpenTelemetry feature and
2) Update the default cluster version to 1.35.5-gke.1163012 which is the
current [regular channel default
version](https://docs.cloud.google.com/kubernetes-engine/docs/release-notes#current_versions)
to fix https://github.com/agent-substrate/substrate/issues/341

Tested:
* Successfully recreated GKE cluster, redeployed ate-system and ran
counter demo.
2026-06-30 16:20:05 -07:00
Max Smythe 6527f56095 move benchmarking dependencies under a /benchmarking/ directory 2026-06-30 14:32:47 -07:00
Max Smythe 1ec8fd2d2c verify licenses of Python dependencies 2026-06-30 14:32:47 -07:00
Max Smythe 18ca637074 streamline locust install + fix performance bugs 2026-06-30 14:32:47 -07:00
Benjamin Elder 3d53de85eb microvm MVP cleanup: align rootfs behavior to gvisor, ... (#313)
Follow-up to https://github.com/agent-substrate/substrate/pull/287 /
#123

- align snapshot behavior: use a tmpfs (for writes) on top of read-only
viritio-fs mount for the container image rootfs instead of ext4 images
- enable multiple container support
- cleanup stale comments

> It's a good idea to open an issue first for discussion.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR
2026-06-26 20:02:11 -07:00
dependabot[bot] 50a68bc146 build(deps): bump github.com/sigstore/rekor in /hack/tools/ko
Bumps [github.com/sigstore/rekor](https://github.com/sigstore/rekor) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/sigstore/rekor/releases)
- [Changelog](https://github.com/sigstore/rekor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/rekor/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/sigstore/rekor
  dependency-version: 1.5.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-26 17:22:14 -07:00
Jet Chiang f01fbe20ef review comments
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
2026-06-25 16:51:46 -07:00
Jet Chiang 1da2a48033 delete actors in demo scripts
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
2026-06-25 16:51:46 -07:00
Mesut Oezdil 2560f931dc fix: misc doc fixes across multiple files (#310)
- roadmap.md: remove empty bullet point
- hack/update/README.md: fix self-referential path (`../update` ->
`../update-all.sh`)
- hack/verify/README.md: fix self-referential path (`../verify` ->
`../verify-all.sh`)
- cmd/atenet/internal/dns/README.md: fix typo (`orchsterates` ->
`orchestrates`)
- docs/dev/valkey-direct-access.md: add context and warning about
destructive commands
2026-06-25 15:25:20 -07:00
Benjamin Elder 21fed4ee78 address review: hack tooling cleanups
- ateom-base Dockerfile: full apt cleanup (apt-get clean + rm tmp).
- stage-to-rustfs.sh: fail fast when the aws CLI is missing.
2026-06-25 13:44:25 -07:00
Benjamin Elder 2c50d282e2 hack,demos,docs: micro-VM asset tooling, base image, demo runner, docs
Assemble + stage the micro-VM runtime assets, an ateom-base image (debian-slim +
e2fsprogs for mkfs.ext4), and run-microvm-demo.sh to build + deploy the
counter-microvm demo end to end (overriding the worker base via KO_CONFIG_PATH so
no committed file is edited). Document the micro-VM sandbox class.
2026-06-25 13:44:25 -07:00
Benjamin Elder 387acac541 hack/update/licenses.sh: mirror in-tree third_party licenses
go-licenses only covers module dependencies and treats our own module —
including any copied-in / forked third-party SOURCE under in-tree
third_party/ dirs — as first-party, so those upstream LICENSE/NOTICE/
COPYING files are never collected.

Mirror them into LICENSES/third_party/, keyed by their path under
third_party/, the same way kubernetes' hack/update-vendor-licenses.sh
does. `git ls-files` is used so gitignored paths are skipped; vendor/ and
the output dir are excluded since they hold module deps / generated
output rather than forked source.

This is a no-op today (there is no in-tree third_party source yet) and
prepares the licenses tooling for forthcoming vendored third-party code.
2026-06-23 14:56:58 -07:00
Benjamin Elder 00a90a8eda Decouple Sandbox Binaries / Config from ActorTemplate (#261)
Fixes https://github.com/agent-substrate/substrate/issues/253

> It's a good idea to open an issue first for discussion.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR

Should make something like
https://github.com/agent-substrate/substrate/pull/239 less awkward, and
also https://github.com/agent-substrate/substrate/issues/255 (we don't
have to cram more fields into actortemplate for the shim binary and
update _all_ of the demo actortemplates to include them).
2026-06-17 09:46:46 -07:00