Skip to content

feat(gateway): use an explicit callback-only endpoint for local sandboxes #2538

Description

@elezar

Problem Statement

Local sandbox supervisors need to call back into the gateway. Today, when a Docker or Podman topology can already reach the configured primary listener, the driver can request no additional listener and the injected callback URI still targets that primary listener. The primary listener intentionally exposes the full multiplexed gateway surface, including user and administrator gRPC APIs, health and reflection, HTTP routes, WebSocket tunnel handling, and service-routing/parser paths.

This behavior predates #2492. That PR narrows separately negotiated callback listeners to sandbox-callable gRPC methods and removes broad wildcard primary binds from local Docker and Podman paths, but it does not create a distinct callback surface when the primary listener already satisfies reachability.

Normal sandbox JWT authorization rejects most non-callback calls, but reachability is still broader than necessary. Some routes are intentionally unauthenticated, parser and routing code remains reachable, and allow_unauthenticated_users is a valid supported local-driver configuration that cannot simply be prohibited. The security boundary should therefore not depend solely on normal request authentication.

Related design and implementation context: #2215 and #2492.

Proposed Design

Give every supervisor-backed local sandbox an explicit gateway-owned callback URI, even when its driver reports that no additional listener is required.

Preserve two independent layers:

  1. The gateway owns callback endpoint identity, API purpose, and the callback method allowlist. A callback endpoint accepts only sandbox-callable gRPC methods and rejects user and administrator APIs, health, reflection, non-callback inference APIs, and HTTP routes before normal request authentication.
  2. The compute driver reports only the network reachability that its runtime requires. An empty requirement means that the explicit callback endpoint is already reachable from the sandbox; it must not mean that the primary multiplexed API URI should be reused.

Start with one gateway-owned callback URI that is injected for each sandbox create, with sandbox-scoped credentials remaining separate from endpoint selection. Avoid persistent per-driver endpoint state. Docker, Podman, and future supervisor-backed local drivers should implement the same contract.

The investigation must settle these implementation choices before build work begins:

  • Whether the callback surface always uses a distinct port, and whether that port has a deterministic configurable default or is allocated dynamically.
  • Whether a single-port deployment must remain possible through SNI, another transport discriminator, or an explicitly documented compatibility mode.
  • How TLS identity, certificates, sandbox JWTs, sandbox mTLS, and unauthenticated local configurations interact with the callback-only pre-authentication filter.
  • How older or external drivers negotiate support and what migration behavior applies when the listener-requirements RPC is unimplemented.
  • How RPM, local development, Docker Desktop, Podman Machine, native Linux bridges, firewalls, container publishing, and HA advertise and preserve the callback URI.
  • How existing sandboxes reconnect across gateway restart or endpoint changes.

Acceptance criteria

  • Enumerate local topologies where sandbox callback traffic currently reaches the primary listener, including native Linux Docker, Docker Desktop, native/rootless Podman, and Podman Machine.
  • Exercise representative administrator and user calls through the callback path with a sandbox JWT, sandbox mTLS without a JWT, invalid credentials, and no credentials.
  • Inventory unauthenticated gRPC and HTTP routes and identify parser, router, tunnel, reflection, health, and service-routing surfaces reachable from each callback topology.
  • Include supported auth-disabled and allow_unauthenticated_users local configurations in the threat and compatibility analysis.
  • Decide whether a callback-only endpoint is mandatory for every supervisor-backed local driver, including when no extra reachability listener is requested.
  • Decide fixed/configurable-default versus ephemeral port allocation and document whether and how single-port deployments remain supported.
  • Specify the gateway-provided callback URI contract separately from driver-provided reachability requirements.
  • Define capability/version negotiation and migration for old and external drivers.
  • Cover TLS, credentials, packaging, firewall, restart, and HA behavior.
  • Document the intended callback security boundary and add regression tests proving that non-callback gRPC and all HTTP routes are rejected on the explicit endpoint.

Alternatives Considered

  1. Keep using the primary listener when no extra reachability is required. This preserves current behavior but leaves the callback boundary dependent on credentials and exposes unrelated parser and routing surfaces.
  2. Prohibit unauthenticated local-driver configurations. This would remove a valid existing use case and would not eliminate the value of reducing reachable surface for authenticated deployments.
  3. Treat authentication as the only boundary. Sandbox JWT authorization is necessary, but it acts after parts of the transport and routing stack and does not cover every intentionally unauthenticated route.
  4. Let each driver choose the callback URI and exposed API. This mixes runtime reachability with gateway authorization, makes external-driver authority too broad, and reintroduces driver-specific state.
  5. Restrict only additional negotiated listeners, as in feat(compute): negotiate gateway callback listeners #2492. This is a useful immediate improvement but does not cover topologies where callbacks reuse the primary listener.
  6. Preserve one port and distinguish callback traffic by credentials or TLS identity. This may reduce packaging changes, but it must demonstrate that non-callback traffic can be rejected early and that unauthenticated local configurations remain well defined.

Agent Investigation

Checklist

  • I have reviewed existing issues and the architecture docs.
  • This is a design proposal, not a please build this request.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions