Documentation
¶
Index ¶
- Constants
- func BridgeRuntimeLLMStreamResponse(c echo.Context, resp *http.Response, req runtimeLLMStreamBridgeRequest) error
- func EgressDispatchHandler(daemon http.Handler, egress http.Handler) http.Handler
- func IsHTTPRequestBodyTooLarge(err error) bool
- func IsRuntimeLLMFacadeRequest(r *http.Request) bool
- func JupyterTargetReachable(proxyState domain.ProxyState, timeout time.Duration) bool
- func NewRuntimeLLMHTTPClient(responseHeaderTimeout time.Duration) *http.Client
- func RegisterJupyterRoutes(app *echo.Echo, opts JupyterOptions)
- func RegisterRuntimeLLMFacadeRoutes(app *echo.Echo, opts RuntimeLLMOptions)
- func RegisterWorkspaceRoutes(app *echo.Echo, opts WorkspaceOptions)
- func ToWorkspaceHTTPError(err error) error
- func ToWorkspaceUploadHTTPError(err error) error
- func WriteRuntimeLLMEncodedError(c echo.Context, raw []byte, status int) error
- type EgressProxy
- type EgressProxyAuthorizer
- type EgressProxyOptions
- type EgressProxyPolicySource
- type EgressProxyRecorder
- type EgressProxySessionPolicySource
- type EnsureReadyFunc
- type HTTPDoer
- type JupyterOptions
- type RuntimeLLMConnectionResolver
- type RuntimeLLMOptions
- type RuntimeLLMSandboxStore
- type RuntimeLLMTokenStore
- type Store
- type WorkspaceFilesResponse
- type WorkspaceLoader
- type WorkspaceOptions
Constants ¶
const ( // EgressRuleBlockedAddress denies a destination that resolves to an // address the engine never forwards to, whatever the policy says. It is // what keeps the proxy from becoming a new way to reach the daemon's own // loopback services or a cloud metadata endpoint. EgressRuleBlockedAddress = "engine.blocked-address" // read. An unreadable declaration is not an absent one, so the proxy denies // rather than forwarding on a policy it could not evaluate. EgressRulePolicyUnavailable = "engine.policy-unavailable" // EgressRuleUnresolvedAddress denies when the destination does not resolve. EgressRuleUnresolvedAddress = "engine.unresolved-address" // EgressRuleBlockedPort denies a control-plane port the engine never // forwards to, whatever the policy says. A sandbox that could reach a // cluster's etcd or kubelet through the proxy would have a path to the // credentials and the workloads of the platform hosting it, so the // declaration cannot buy that path back. EgressRuleBlockedPort = "engine.blocked-port" // injected credential could not be resolved from the daemon environment. EgressRuleCredentialUnavailable = "engine.credential-unavailable" // paths when the proxy cannot inspect the request. A declaration that asked // for L7 enforcement is not silently downgraded to a destination-only // allowance: either the deployment opts into TLS interception (and the guest // trusts the CA) or the connection is refused. EgressRuleL7Unavailable = "engine.l7-inspection-unavailable" )
Engine-owned rule IDs. They are stable so a decision record names the rule that produced it, and a deny reason never depends on a project's wording.
const DefaultEgressDialTimeout = 30 * time.Second
DefaultEgressDialTimeout bounds how long the proxy waits for an upstream connection it opened for a sandbox.
const RuntimeLLMFacadePrefix = "/api/runtime/sandboxes/"
Variables ¶
This section is empty.
Functions ¶
func EgressDispatchHandler ¶
EgressDispatchHandler routes a guest's forward-proxy traffic to the egress proxy and everything else to the daemon's own handler, so the proxy is served on the listener a sandbox can already reach instead of a second port a deployment would have to publish.
A request is treated as proxy traffic when it names an absolute target (the form only a proxy client produces) or when it is a CONNECT carrying a proxy credential. A CONNECT without one is left to the daemon: the daemon's own HTTP/2 clients may use the method, and the proxy answers an unauthenticated CONNECT with 407, which would turn that client's request into an authentication error. The credential is therefore what marks the request as the proxy's, and the proxy is the only producer of it.
func JupyterTargetReachable ¶
func JupyterTargetReachable(proxyState domain.ProxyState, timeout time.Duration) bool
func NewRuntimeLLMHTTPClient ¶
NewRuntimeLLMHTTPClient creates an upstream client that bounds the wait for response headers without imposing a total deadline on streaming responses.
func RegisterJupyterRoutes ¶
func RegisterJupyterRoutes(app *echo.Echo, opts JupyterOptions)
func RegisterRuntimeLLMFacadeRoutes ¶
func RegisterRuntimeLLMFacadeRoutes(app *echo.Echo, opts RuntimeLLMOptions)
func RegisterWorkspaceRoutes ¶
func RegisterWorkspaceRoutes(app *echo.Echo, opts WorkspaceOptions)
func ToWorkspaceHTTPError ¶
Types ¶
type EgressProxy ¶
type EgressProxy struct {
// contains filtered or unexported fields
}
EgressProxy is the daemon-side forward proxy a sandbox's outbound traffic passes through. It authenticates the sandbox, decides the destination against that sandbox's current policy, and only then opens the connection, so the declared policy is enforced by the engine instead of by a driver feature.
It is an HTTP forward proxy: it accepts absolute-form requests and CONNECT tunnels. It is not an open proxy — a request without a sandbox credential is answered 407 and never decided.
func NewEgressProxy ¶
func NewEgressProxy(options EgressProxyOptions) (*EgressProxy, error)
NewEgressProxy validates the required dependencies and returns the proxy.
func (*EgressProxy) ServeHTTP ¶
func (p *EgressProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the forward-proxy surface. Every decision it makes — including a refusal that comes from the engine rather than from the declared policy — is accounted for through the recorder, because a blocked attempt is exactly what an operator needs to see.
type EgressProxyAuthorizer ¶
type EgressProxyAuthorizer interface {
AuthorizeEgressProxy(ctx context.Context, claimedSandboxID, credential string) (sandboxID string, err error)
}
EgressProxyAuthorizer resolves the sandbox a proxy credential belongs to. It receives the sandbox name the caller claimed so an implementation can verify the credential against that identity rather than trusting either half alone. A credential that names no sandbox (unknown, revoked, expired, malformed) is an error: the proxy never decides for an unidentified caller.
type EgressProxyOptions ¶
type EgressProxyOptions struct {
Authorizer EgressProxyAuthorizer
Policies EgressProxyPolicySource
SessionPolicies EgressProxySessionPolicySource
Recorder EgressProxyRecorder
Logger *slog.Logger
// LookupIP resolves the destination of a request. It defaults to the
// process resolver; a test injects one so a decision never depends on real
// name resolution.
LookupIP func(ctx context.Context, host string) ([]net.IP, error)
// DialTimeout bounds the connection this proxy opens on the sandbox's
// behalf. Zero uses DefaultEgressDialTimeout.
DialTimeout time.Duration
// Dial opens the upstream connection. It is nil in production, where the
// proxy uses its own dialer; a test injects one to exercise the decision
// and forwarding paths without reaching a real network.
Dial func(ctx context.Context, network, address string) (net.Conn, error)
// TLSMITM enables L7 TLS termination for an HTTPS allowance that declares
// methods or paths. It is opt-in: with it off, such an allowance fails
// closed rather than being forwarded uninspected.
TLSMITM bool
// CACertificatePEM and CAKeyPEM are the CA the proxy signs leaves with. When
// both are empty and TLSMITM is true, the proxy generates an ephemeral CA.
CACertificatePEM []byte
CAKeyPEM []byte
// UpstreamTLSConfig is the base TLS configuration for the connection the
// proxy opens to the real upstream after intercepting. Nil uses the system
// roots. A test supplies a pool that trusts its local upstream certificate.
UpstreamTLSConfig *tls.Config
}
EgressProxyOptions configures an EgressProxy. Authorizer and Policies are required; the remaining fields have production defaults.
type EgressProxyPolicySource ¶
type EgressProxyPolicySource interface {
EgressProxyPolicy(ctx context.Context, sandboxID string) (egress.Policy, error)
}
EgressProxyPolicySource returns the egress policy that currently governs one sandbox. The proxy reads it per request rather than caching it for the life of a tunnel, which is what makes a policy change take effect on a sandbox that is already running.
type EgressProxyRecorder ¶
type EgressProxyRecorder interface {
RecordEgressDecision(ctx context.Context, record egress.Record)
}
EgressProxyRecorder receives one account of every decision. It is optional: a composition without one still enforces, it just does not persist the record.
type EgressProxySessionPolicySource ¶
type EgressProxySessionPolicySource interface {
EgressProxyPolicyForSession(ctx context.Context, sandboxID, sessionID, marker string) (egress.Policy, error)
}
EgressProxySessionPolicySource is the optional per-run hook: when a caller supplies it, the proxy asks for a policy scoped to the sandbox-init session instead of the sandbox-wide policy. A source that has no per-session policy returns the sandbox policy unchanged, so implementing this interface does not change behavior until a deployment actually stores per-run policies.
type EnsureReadyFunc ¶
type JupyterOptions ¶
type JupyterOptions struct {
BasePath string
Store Store
EnsureReady EnsureReadyFunc
// Logger receives the readiness and upstream failures that the handler does
// not return to the client. It defaults to slog.Default.
Logger *slog.Logger
}
type RuntimeLLMConnectionResolver ¶
type RuntimeLLMConnectionResolver func(ctx context.Context, connectionID, model string) (llms.ResolvedTarget, error)
RuntimeLLMConnectionResolver resolves the upstream target of the connection a facade token is bound to, for one literal upstream model.
The token names the connection, so a proxied call never selects one: it looks up the connection the run was prepared with and forwards the requested model to it. That is what makes the daemon a weak caller — it holds an address and a credential, and the upstream decides which models it serves.
type RuntimeLLMOptions ¶
type RuntimeLLMOptions struct {
Tokens RuntimeLLMTokenStore
Sandboxes RuntimeLLMSandboxStore
Connections RuntimeLLMConnectionResolver
Client HTTPDoer
// MaxOutputTokens, when > 0, is injected into every proxied upstream LLM
// request using the field names supported by the upstream protocol. codex
// does not send max_output_tokens itself, so without this API proxies that
// default to a small limit silently truncate long outputs.
MaxOutputTokens int
// Logger records why a proxied call failed. The guest receives a fixed
// message, so the log is the only place the cause survives. Defaults to
// slog.Default.
Logger *slog.Logger
}
type RuntimeLLMSandboxStore ¶
type RuntimeLLMTokenStore ¶
type WorkspaceFilesResponse ¶
type WorkspaceFilesResponse struct {
WorkspaceID string `json:"workspace_id"`
Files []workspaces.FileEntry `json:"files"`
}
type WorkspaceLoader ¶
type WorkspaceLoader func(ctx context.Context, workspaceID string) (domain.WorkspaceConfig, workspaces.FileWorkspaceContent, error)
type WorkspaceOptions ¶
type WorkspaceOptions struct {
UploadLimitBytes int64
Load WorkspaceLoader
}