Documentation
¶
Overview ¶
Package gateway implements the fenced Tool Gateway boundary that runtime workers call on behalf of an Attempt. The gateway enforces policy, approval binding, budget hard-stop and durable side-effect receipts outside the LLM; it is a separate process in production (tech baseline §5) because it sits on the credential and external-side-effect security boundary.
Index ¶
- type DevExecutor
- type DevSecretBroker
- type IPCService
- func (s *IPCService) AcknowledgeMessage(ctx context.Context, request *ipcv1.AcknowledgeMessageRequest) (*ipcv1.AcknowledgeMessageResponse, error)
- func (s *IPCService) ReceiveMessages(ctx context.Context, request *ipcv1.ReceiveMessagesRequest) (*ipcv1.ReceiveMessagesResponse, error)
- func (s *IPCService) SendMessage(ctx context.Context, request *ipcv1.SendMessageRequest) (*ipcv1.SendMessageResponse, error)
- type MailboxScope
- type MemoryInvoker
- type MemoryService
- type ModelInvocationService
- type ModelInvoker
- type ModelRunner
- type ModelService
- func (s *ModelService) Begin(ctx context.Context, request *modelv1.BeginRequest) (*modelv1.BeginResponse, error)
- func (s *ModelService) Finish(ctx context.Context, request *modelv1.FinishRequest) (*modelv1.FinishResponse, error)
- func (s *ModelService) Settle(ctx context.Context, request *modelv1.SettleRequest) (*modelv1.SettleResponse, error)
- type PeerAuthorizer
- type PeerPolicy
- type RuntimeFence
- type Service
- func (s *Service) InvokeTool(ctx context.Context, request *gatewayv1.InvokeToolRequest) (*gatewayv1.InvokeToolResponse, error)
- func (s *Service) ListTools(ctx context.Context, request *gatewayv1.ListToolsRequest) (*gatewayv1.ListToolsResponse, error)
- func (s *Service) WithRuntimeFence(fences RuntimeFence) *Service
- type SyscallService
- type ToolInvoker
- type WebhookExecutor
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type DevExecutor ¶
type DevExecutor struct {
MaxOutputBytes int64
}
DevExecutor is the v0.1 development tool executor: it echoes the normalized invocation for any registered tool and enforces nothing beyond the gateway decision chain. It is not a sandbox and must never be deployed with real credentials or untrusted workloads.
func (*DevExecutor) Execute ¶
func (e *DevExecutor) Execute(_ context.Context, request tool.ExecutionRequest) (tool.ExecutionResult, error)
type DevSecretBroker ¶
type DevSecretBroker struct {
Handle tool.SecretHandle
}
DevSecretBroker issues a fixed handle for development. It is not a real secret broker; the gateway redacts the handle from results, which is what exercises the sanitizer in dev.
func (*DevSecretBroker) Issue ¶
func (d *DevSecretBroker) Issue(context.Context, tool.SecretScope) (tool.SecretHandle, error)
type IPCService ¶
type IPCService struct {
ipcv1.UnimplementedIPCGatewayServiceServer
// contains filtered or unexported fields
}
IPCService is the fenced agent-to-agent mailbox boundary. Agents reach their mailbox through this service rather than through the Control API, so they cannot choose a tenant, and can never address a mailbox outside their own run.
Authorization is two layers, checked in the order the tool and model path uses (service-layer capability first, then Rego):
- capability: the sending AgentVersion must grant the receiving one in capabilities.peers. Grants are per immutable version, so republishing a version is what changes them.
- tenant policy: the tenant must list the receiving AgentVersion in allowed_peers. This is per tenant and denies by default, so a tenant that has not opted in cannot message anyone regardless of its versions' grants.
Two things it deliberately still does not do:
- It does not notify a receiver. The platform cannot push into a running agent: fenced.runtime.v1 exposes seven pull RPCs, its HeartbeatResponse carries no payload, and nothing in the repository resembles a wake path. A receiver drains its mailbox on its own schedule.
- It does not check the *receiver's* willingness. The grant answers "may I write to you", never "may you write to me", so a sender that knows a run id can reach it. A receiving-side allowlist is a separate design.
func NewIPCService ¶
func NewIPCService( mailbox store.IPCStore, scopes MailboxScope, fences RuntimeFence, allowedTenant string, capabilities PeerAuthorizer, peerPolicy PeerPolicy, ) *IPCService
func (*IPCService) AcknowledgeMessage ¶
func (s *IPCService) AcknowledgeMessage(ctx context.Context, request *ipcv1.AcknowledgeMessageRequest) (*ipcv1.AcknowledgeMessageResponse, error)
AcknowledgeMessage records the caller's receipts for a batch it has drained.
func (*IPCService) ReceiveMessages ¶
func (s *IPCService) ReceiveMessages(ctx context.Context, request *ipcv1.ReceiveMessagesRequest) (*ipcv1.ReceiveMessagesResponse, error)
ReceiveMessages drains the caller's own mailbox. The request carries no address on purpose: the only mailbox a caller may drain is the one owned by its fenced run, so the address is derived from the fenced assignment rather than from anything the caller sent.
func (*IPCService) SendMessage ¶
func (s *IPCService) SendMessage(ctx context.Context, request *ipcv1.SendMessageRequest) (*ipcv1.SendMessageResponse, error)
SendMessage stores one message in the mailbox its address names.
type MailboxScope ¶
type MailboxScope interface {
GetRunMailboxScope(context.Context, string, uuid.UUID) (store.RunMailboxScope, error)
}
MailboxScope resolves the mailbox a run id names.
type MemoryInvoker ¶
type MemoryInvoker interface {
Put(context.Context, memory.PutInput) (store.MemoryRecord, bool, error)
Search(context.Context, memory.SearchInput) ([]store.MemoryRecord, error)
}
MemoryInvoker is the canonical memory decision chain exposed to Agents.
type MemoryService ¶
type MemoryService struct {
gatewayv1.UnimplementedMemoryGatewayServiceServer
// contains filtered or unexported fields
}
MemoryService is a fenced, capability-aware Agent memory boundary. The existing Control API remains an operator surface; Agent runtimes use this service so they cannot choose a tenant, version, or namespace grant.
func NewMemoryService ¶
func NewMemoryService(memories MemoryInvoker, fences RuntimeFence, allowedTenant string, capabilities *capability.Authorizer) *MemoryService
func (*MemoryService) PutMemory ¶
func (s *MemoryService) PutMemory(ctx context.Context, request *gatewayv1.PutMemoryRequest) (*gatewayv1.PutMemoryResponse, error)
func (*MemoryService) SearchMemory ¶
func (s *MemoryService) SearchMemory(ctx context.Context, request *gatewayv1.SearchMemoryRequest) (*gatewayv1.SearchMemoryResponse, error)
type ModelInvocationService ¶
type ModelInvocationService struct {
modelv1.UnimplementedModelInvocationServiceServer
// contains filtered or unexported fields
}
ModelInvocationService is the additive v1 execution surface of the Model Gateway: it runs policy, budget and the call ledger around a real provider invocation and streams the completion. Credentials never cross this boundary in either direction.
func NewModelInvocationService ¶
func NewModelInvocationService(runner ModelRunner, allowedTenant string, capabilities ...*capability.Authorizer) *ModelInvocationService
NewModelInvocationService builds the execution surface. allowedTenant "*" disables the static tenant gate (production relies on SPIFFE mTLS).
func (*ModelInvocationService) Invoke ¶
func (s *ModelInvocationService) Invoke(request *modelv1.InvokeRequest, stream modelv1.ModelInvocationService_InvokeServer) error
Invoke executes one model invocation. Content deltas stream as chunks; the terminal chunk is either a finish (ledger metadata and the assembled content) or a structured provider failure. Governance failures (identity, capability, policy, budget) are gRPC status errors — no stream is opened.
type ModelInvoker ¶
type ModelInvoker interface {
Begin(context.Context, model.BeginInput) (model.BeginResult, error)
GetModelCall(context.Context, string, uuid.UUID) (store.ModelCall, error)
Settle(context.Context, store.ModelCall, int64, model.Usage) error
Finish(context.Context, store.ModelCall, model.FinishInput) (store.ModelCall, error)
}
ModelInvoker is the fenced model decision chain the service exposes. The model.Gateway satisfies it.
type ModelRunner ¶
type ModelRunner interface {
InvokeStream(context.Context, model.InvokeInput, func(string)) (model.InvokeOutput, error)
}
ModelRunner executes real model invocations behind the fenced decision chain. The model.Invoker satisfies it.
type ModelService ¶
type ModelService struct {
modelv1.UnimplementedModelGatewayServiceServer
// contains filtered or unexported fields
}
ModelService is the fenced gRPC surface of the Model Gateway. Development mode accepts a fixed tenant on a loopback-only listener; production exposure requires SPIFFE mTLS.
func NewModelService ¶
func NewModelService(invoker ModelInvoker, allowedTenant string, capabilities ...*capability.Authorizer) *ModelService
func (*ModelService) Begin ¶
func (s *ModelService) Begin(ctx context.Context, request *modelv1.BeginRequest) (*modelv1.BeginResponse, error)
func (*ModelService) Finish ¶
func (s *ModelService) Finish(ctx context.Context, request *modelv1.FinishRequest) (*modelv1.FinishResponse, error)
func (*ModelService) Settle ¶
func (s *ModelService) Settle(ctx context.Context, request *modelv1.SettleRequest) (*modelv1.SettleResponse, error)
type PeerAuthorizer ¶
type PeerAuthorizer interface {
Authorize(context.Context, string, string, capability.Kind, ...string) error
}
PeerAuthorizer decides whether the sending AgentVersion holds an immutable grant for the receiving one. *capability.Authorizer satisfies it.
type PeerPolicy ¶
type PeerPolicy interface {
EvaluatePeer(context.Context, string, policy.PeerContext) policy.Decision
}
PeerPolicy is the tenant-wide half of the same decision: whether this tenant may message that AgentVersion at all. *policy.Engine satisfies it.
It is a narrow consumer-side interface for the same reason tool and model gateways declare their own: the service depends on one method, not on the policy engine's shape.
type RuntimeFence ¶
type RuntimeFence interface {
GetRuntimeAssignment(context.Context, string, uuid.UUID, int64) (store.RuntimeAssignment, error)
}
RuntimeFence resolves an Attempt only when its fencing token is current.
type Service ¶
type Service struct {
gatewayv1.UnimplementedToolGatewayServiceServer
// contains filtered or unexported fields
}
Service is the fenced gRPC surface of the Tool Gateway. Development mode accepts a fixed tenant on a loopback-only listener; production exposure requires SPIFFE mTLS (ADR-006).
func NewService ¶
func NewService(invoker ToolInvoker, allowedTenant string, capabilities ...*capability.Authorizer) *Service
func (*Service) InvokeTool ¶
func (s *Service) InvokeTool(ctx context.Context, request *gatewayv1.InvokeToolRequest) (*gatewayv1.InvokeToolResponse, error)
func (*Service) ListTools ¶
func (s *Service) ListTools(ctx context.Context, request *gatewayv1.ListToolsRequest) (*gatewayv1.ListToolsResponse, error)
func (*Service) WithRuntimeFence ¶
func (s *Service) WithRuntimeFence(fences RuntimeFence) *Service
WithRuntimeFence attaches a fence validator to the tool gateway service.
type SyscallService ¶
type SyscallService struct {
// contains filtered or unexported fields
}
SyscallService exposes the unified Agent Syscall ABI over HTTP.
func NewSyscallService ¶
func NewSyscallService(dispatcher *syscall.SyscallDispatcher, allowedTenant string) *SyscallService
NewSyscallService creates a new SyscallService.
func (*SyscallService) Dispatcher ¶
func (s *SyscallService) Dispatcher() *syscall.SyscallDispatcher
Dispatcher returns the underlying kernel SyscallDispatcher.
func (*SyscallService) ServeHTTP ¶
func (s *SyscallService) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP handles HTTP POST requests for unified system call dispatching.
type ToolInvoker ¶
type ToolInvoker interface {
InvokeTool(context.Context, tool.InvokeInput) (tool.InvokeResult, error)
ListTools(context.Context, string) ([]store.ToolDescriptor, error)
GetToolDescriptor(ctx context.Context, tenantID, name, version string) (store.ToolDescriptor, error)
}
ToolInvoker is the decision chain the service exposes. The tool.Gateway satisfies it; tests substitute fakes.
type WebhookExecutor ¶
type WebhookExecutor struct {
// contains filtered or unexported fields
}
WebhookExecutor is the production tool adapter boundary. Every immutable tool version maps to one preconfigured HTTPS endpoint; Agent input can never select or modify the destination.
func NewWebhookExecutor ¶
func (*WebhookExecutor) Execute ¶
func (e *WebhookExecutor) Execute(ctx context.Context, input tool.ExecutionRequest) (tool.ExecutionResult, error)