Documentation
¶
Overview ¶
Package codexexecgateway: types are defined in execmodel to avoid an import cycle with the handlers sub-package. Type aliases here re-export them under the parent package name so existing code outside this package is unaffected.
Index ¶
- Variables
- type CapPayload
- type Config
- type ConnRegistry
- type ConnectedExecutor
- type Executor
- type RevokedSet
- type Server
- type Store
- func (s *Store) BindWorkspaceExecutor(ctx context.Context, workspaceID, exeID, name, description string, ...) error
- func (s *Store) Close() error
- func (s *Store) ConnectedExecutorsForWorkspace(ctx context.Context, workspaceID string, connectedIDs []string) ([]ConnectedExecutor, error)
- func (s *Store) CreateExecutor(ctx context.Context, e Executor, registrationTokenHash string) error
- func (s *Store) DeleteExecutor(ctx context.Context, exeID string) error
- func (s *Store) GetExecutor(ctx context.Context, exeID string) (*Executor, error)
- func (s *Store) GetRegistrationTokenHash(ctx context.Context, exeID string) (string, error)
- func (s *Store) ListWorkspaceExecutors(ctx context.Context, workspaceID string) ([]ConnectedExecutor, error)
- func (s *Store) OwnsExecutor(ctx context.Context, workspaceID, exeID string) (bool, error)
- func (s *Store) UnbindWorkspaceExecutor(ctx context.Context, workspaceID, exeID string) error
- func (s *Store) UpdateLastSeen(ctx context.Context, exeID string) error
- type WorkspaceExecutor
Constants ¶
This section is empty.
Variables ¶
Functions ¶
This section is empty.
Types ¶
type CapPayload ¶
type CapPayload struct {
TurnID string `json:"turn_id"`
WorkspaceID string `json:"workspace_id"`
IAT int64 `json:"iat"`
EXP int64 `json:"exp"`
}
CapPayload is the parsed JSON payload from a CODEX_EXEC_GATEWAY_TOKEN.
Per the 2026-05-16 fixed-tools redesign, tokens are workspace-scoped: a single token authorises any exe_id bound to the named workspace. The /bridge handler verifies workspace ownership against the workspace_executors table at request time, replacing the prior exe_ids[] allow-list shipped in the payload.
func VerifyCapabilityToken ¶
func VerifyCapabilityToken(token string, secret []byte) (CapPayload, error)
VerifyCapabilityToken parses and verifies a 3-part HMAC capability token.
Token format (spec § Capability token):
token = base64url(header) "." base64url(payload) "." base64url(sig)
header = '{"alg":"HS256","typ":"CXG"}'
payload = '{"turn_id":"...","workspace_id":"...","iat":...,"exp":...}'
sig = HMAC-SHA256(secret, base64url(header) "." base64url(payload))
base64url encoding uses no padding (RFC 7515 / JWT convention). HMAC comparison is constant-time via hmac.Equal to prevent timing attacks. Expiry is checked in UTC.
type Config ¶
type Config struct {
Port string
DatabaseURL string
CapTokenHMACSecret []byte
AgentserverInternalSecret string
// AgentserverInternalURL is the http(s):// base for agentserver's internal
// API — used by the SDK REST layer to validate proxy tokens via
// POST /internal/validate-proxy-token. Example: "http://agentserver:8080".
// Required when the SDK routes are enabled.
AgentserverInternalURL string
// SelfHTTPBaseURL is the http(s):// loopback base for this gateway process
// (e.g. "http://localhost:6060"). The SDK name-resolver calls
// /internal/sdk/connected on this host. If empty, the SDK tool layer will
// fail to resolve environment names (envs/list still works).
SelfHTTPBaseURL string
// PublicWSBaseURL is the wss:// origin used in the response of the
// upstream-compat `POST /cloud/executor/{exe_id}/register` endpoint.
// Example: "wss://codex-exec.agent.cs.ac.cn:443". When empty, the
// endpoint synthesises a URL from the incoming request's Host header
// (less reliable behind proxies but useful in dev).
PublicWSBaseURL string
// PublicHTTPSBaseURL is the https:// origin the relay endpoint is
// reachable at — embedded in CreateRelay responses so env-mcp can
// build curl PUT/GET commands. Example:
// "https://codex-exec.agent.cs.ac.cn". When empty, the relay
// /api/exec-gateway/relay/create endpoint refuses to mint tickets
// (env-mcp falls back to the ws cat-pump path).
PublicHTTPSBaseURL string
// RelayDefaultTTL caps how long a minted ticket waits for both
// sides to connect before timing out. Defaults to 5 minutes.
RelayDefaultTTL time.Duration
// RelayMaxPerWorkspace caps concurrent relays per workspace.
// Defaults to 16; protects gateway memory from runaway agents.
RelayMaxPerWorkspace int
LogLevel slog.Level
}
WebSocket keepalive (ping interval + idle timeout) is phase-2; nhooyr's defaults govern for now.
func LoadConfigFromEnv ¶
type ConnRegistry ¶
type ConnRegistry struct {
// contains filtered or unexported fields
}
ConnRegistry tracks the single live inbound /codex-exec/{exe_id} connection per exe_id. Each entry is wrapped in an *inboundConn that can host multiple concurrent /bridge sessions multiplexed by stream_id (per the 2026-05-17 redesign).
Re-registering an exe_id evicts the prior inboundConn; the caller MUST call close() on the evicted conn so its routes get fanned out and the underlying ws closes.
func NewConnRegistry ¶
func NewConnRegistry() *ConnRegistry
func (*ConnRegistry) ConnectedIDs ¶
func (r *ConnRegistry) ConnectedIDs() []string
ConnectedIDs returns a snapshot of currently registered exe_ids.
func (*ConnRegistry) Lookup ¶
func (r *ConnRegistry) Lookup(exeID string) (*inboundConn, bool)
Lookup returns the registered inbound for exeID, if any.
func (*ConnRegistry) Register ¶
func (r *ConnRegistry) Register(exeID string, ic *inboundConn) (evicted *inboundConn)
Register inserts ic for exeID. If a previous inboundConn was registered for the same exeID, returns it as evicted. The caller MUST close the evicted inbound; failing to do so leaks its reader goroutine and orphans its bridge sessions.
func (*ConnRegistry) Unregister ¶
func (r *ConnRegistry) Unregister(exeID string, ic *inboundConn)
Unregister removes exeID only if its current value is ic. This guards against a goroutine for an old inbound deleting a freshly registered one after eviction.
type ConnectedExecutor ¶
type ConnectedExecutor = execmodel.ConnectedExecutor
type Executor ¶
Re-export aliases preserve the package's external API. *Executor and *execmodel.Executor are the same type — aliases are zero-cost.
type RevokedSet ¶
type RevokedSet struct {
// contains filtered or unexported fields
}
RevokedSet is a bounded, concurrent-safe set of revoked turn_ids with per-entry expiry. Designed for the spec's "in-memory revoked set, cap ~10k, periodically pruned of entries past their original exp".
RevokedSet is bounded; when at cap, Add evicts the oldest entry by insertion order, NOT by expiry. If the evicted entry's exp is still in the future, that turn_id is silently un-revoked (its token will pass Contains as if never revoked, until its own exp). Add returns a bool indicating this case so callers can log/alert.
func NewRevokedSet ¶
func NewRevokedSet(cap int) *RevokedSet
func (*RevokedSet) Add ¶
func (r *RevokedSet) Add(turnID string, exp int64) (evictedLive bool)
Add inserts (turnID, exp). Re-adding refreshes the entry's position. When at capacity, the oldest entry is evicted. Returns evictedLive=true if the evicted entry's exp was still in the future — callers should log a warning because that turn_id is no longer blocked by the revoked set.
func (*RevokedSet) Contains ¶
func (r *RevokedSet) Contains(turnID string) bool
Contains reports whether turnID is in the set (regardless of expiry — callers may rely on Prune to clean stale entries).
func (*RevokedSet) Size ¶
func (r *RevokedSet) Size() int
Size returns the current number of entries.
func (*RevokedSet) StartPruner ¶
func (r *RevokedSet) StartPruner(stop <-chan struct{}, interval time.Duration)
StartPruner runs Prune at the given interval until stop is closed. Caller is responsible for closing stop on shutdown.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server bundles the chi router with its dependencies. Server wires the routes for codex-exec-gateway. Production must always be constructed with a real *Store; tests that exercise only auth-rejection paths may use newServerNoStoreForTesting.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides Postgres access for executors + workspace bindings. The underlying *sql.DB is intentionally private: callers must use the declared business methods and cannot bypass them via Exec/Begin/etc.
func (*Store) BindWorkspaceExecutor ¶
func (s *Store) BindWorkspaceExecutor(ctx context.Context, workspaceID, exeID, name, description string, isDefault bool) error
BindWorkspaceExecutor inserts a workspace ↔ executor binding (or upserts name/description/is_default on conflict). The name must be unique per workspace (enforced by uniq_workspace_executors_name); callers should treat a unique-violation as a user-input error and surface "name already taken in this workspace".
func (*Store) ConnectedExecutorsForWorkspace ¶
func (s *Store) ConnectedExecutorsForWorkspace(ctx context.Context, workspaceID string, connectedIDs []string) ([]ConnectedExecutor, error)
ConnectedExecutorsForWorkspace returns the intersection of (workspace's bound executors) ∩ (the connected exe_id list passed in). Used by the internal `/api/exec-gateway/connected` endpoint.
func (*Store) CreateExecutor ¶
CreateExecutor inserts a new executor row. Caller supplies the bcrypt hash.
func (*Store) DeleteExecutor ¶ added in v0.59.1
DeleteExecutor removes the executor row and (via ON DELETE CASCADE) any of its workspace_executors bindings. Used by the orphan-cleanup path in agentserver's Register handler when Bind fails after Register. Idempotent: deleting an absent exe_id is a no-op.
func (*Store) GetExecutor ¶
GetExecutor returns the executor by id, or (nil, nil) if absent.
func (*Store) GetRegistrationTokenHash ¶
GetRegistrationTokenHash returns the bcrypt hash used to authenticate /codex-exec/{exe_id} ws connections.
func (*Store) ListWorkspaceExecutors ¶
func (s *Store) ListWorkspaceExecutors(ctx context.Context, workspaceID string) ([]ConnectedExecutor, error)
ListWorkspaceExecutors returns all bindings for a workspace. Per v0.54.0, name + description come from the workspace_executors row (binding-scoped), not the executor row.
func (*Store) OwnsExecutor ¶ added in v0.51.0
OwnsExecutor reports whether exeID is bound to workspaceID in the workspace_executors table. Used by /bridge to enforce workspace boundary on workspace-scoped cap tokens.
func (*Store) UnbindWorkspaceExecutor ¶
UnbindWorkspaceExecutor removes a binding row.
type WorkspaceExecutor ¶
type WorkspaceExecutor = execmodel.WorkspaceExecutor
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package execmodel holds shared DTOs that cross the codexexecgateway↔handlers package boundary.
|
Package execmodel holds shared DTOs that cross the codexexecgateway↔handlers package boundary. |
|
Package handlers contains HTTP handler functions for the codex-exec gateway.
|
Package handlers contains HTTP handler functions for the codex-exec gateway. |
|
Package relay implements an in-memory ticket-based HTTPS byte relay for codex-exec-gateway.
|
Package relay implements an in-memory ticket-based HTTPS byte relay for codex-exec-gateway. |