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
- func (r *ConnRegistry) AcquireBridge(exeID string) bool
- func (r *ConnRegistry) ConnectedIDs() []string
- func (r *ConnRegistry) Lookup(exeID string) (*websocket.Conn, bool)
- func (r *ConnRegistry) Register(exeID string, c *websocket.Conn) (evicted *websocket.Conn)
- func (r *ConnRegistry) ReleaseBridge(exeID string)
- func (r *ConnRegistry) Unregister(exeID string, c *websocket.Conn)
- type ConnectedExecutor
- type Executor
- type RevokedSet
- type Server
- type Store
- func (s *Store) BindWorkspaceExecutor(ctx context.Context, workspaceID, exeID string, isDefault bool) 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) 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) 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"`
ExeIDs []string `json:"exe_ids"`
IAT int64 `json:"iat"`
EXP int64 `json:"exp"`
}
CapPayload is the parsed JSON payload from a CODEX_EXEC_GATEWAY_TOKEN. Under the 2026-05-10 refinement, tokens minted by codex-app-gateway contain exactly one exe_id. The verification logic accepts any-length exe_ids for forward-compatibility.
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":"...","exe_ids":[...],"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.
func (CapPayload) AllowsExeID ¶
func (p CapPayload) AllowsExeID(exeID string) bool
AllowsExeID reports whether the named exe_id is in the token's allow set.
type Config ¶
type Config struct {
Port string
DatabaseURL string
CapTokenHMACSecret []byte
AgentserverInternalSecret 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
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} ws conn per exe_id. Re-registering an exe_id evicts the prior connection.
func NewConnRegistry ¶
func NewConnRegistry() *ConnRegistry
func (*ConnRegistry) AcquireBridge ¶
func (r *ConnRegistry) AcquireBridge(exeID string) bool
AcquireBridge marks the inbound conn for exeID as having an active bridge session. Returns false if another bridge session already holds it; the caller should reject the new request with HTTP 409 Conflict in that case. Caller MUST call ReleaseBridge when done.
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) (*websocket.Conn, bool)
Lookup returns the registered conn for `exeID`, if any.
func (*ConnRegistry) Register ¶
Register inserts conn for exeID. If a previous conn was registered for the same exeID, returns it as evicted; the caller MUST close the evicted conn — failing to do so leaks the prior handler's goroutine (which is blocked in ws.Read on the now-orphaned conn).
Register also clears any bridge lock for exeID: the prior bridge session's inbound conn is being replaced, so continuing to pump from the old conn would be incorrect.
func (*ConnRegistry) ReleaseBridge ¶
func (r *ConnRegistry) ReleaseBridge(exeID string)
ReleaseBridge releases the bridge lock for exeID. Idempotent.
func (*ConnRegistry) Unregister ¶
func (r *ConnRegistry) Unregister(exeID string, c *websocket.Conn)
Unregister removes `exeID` only if its current value is `c`. This guards against a goroutine for an old conn deleting a new conn 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. store may be nil for smoke tests that don't exercise DB paths; registry and revoked are always constructed.
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 string, isDefault bool) error
BindWorkspaceExecutor inserts a workspace ↔ executor binding (or upserts is_default).
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) 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, joined with executor metadata.
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. |