controlapi

package
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package controlapi contains stateless HTTP handlers for Fort's cloud control plane. Durable state and execution are supplied through explicit ports; a handler must not start a scheduler, runtime, or permanent listener.

Index

Constants

View Source
const (
	// MaximumFunctionBodyBytes is Fort's normative encoded request/response
	// limit, kept below Vercel's platform limit.
	MaximumFunctionBodyBytes = 4 << 20
	ServiceAssertionHeader   = "X-Fort-Service-Assertion"
)
View Source
const (
	// DefaultScheduleCatchUp bounds how much scheduler downtime one invocation
	// reconciles. Older gaps require explicit operator attention rather than an
	// unbounded Vercel invocation.
	DefaultScheduleCatchUp = 5 * time.Minute
	// DefaultScheduleLookAhead materializes the next minute without making its
	// occurrences worker-claimable before their exact due time.
	DefaultScheduleLookAhead = time.Minute
	// MaximumScheduleRoutines and MaximumScheduleOccurrences are hard one-shot
	// work limits. Exceeding either aborts the transaction and its watermark.
	MaximumScheduleRoutines    = 128
	MaximumScheduleOccurrences = 512
	MaximumScheduleLateness    = 90 * time.Second
	// MaximumExpiredWorkerLeaseRecoveries bounds the worker recovery work
	// performed by one scheduled invocation.
	MaximumExpiredWorkerLeaseRecoveries = 128
	// MaximumLateRoutineRunExpirations bounds persisted Routine lateness
	// reconciliation performed by one scheduled invocation.
	MaximumLateRoutineRunExpirations = 128
)
View Source
const (
	WorkerAccountHeader = "X-Fort-Account-ID"
	WorkerIDHeader      = "X-Fort-Worker-ID"
	WorkerMachineHeader = "X-Fort-Machine-ID"
	DefaultWorkerLease  = 2 * time.Minute

	// WorkerOutputMessageRecordType is the authenticated-encryption scope for
	// a renderable terminal output before the control plane persists it as an
	// authoritative Conversation message.
	WorkerOutputMessageRecordType = "worker_output_message"

	MaximumArtifactChunkPlaintextBytes = 2 << 20
	MaximumArtifactChunks              = 64
	MaximumArtifactPlaintextBytes      = 128 << 20
	MaximumArtifactEncodedBytes        = MaximumArtifactChunks * MaximumFunctionBodyBytes
)
View Source
const (
	// MaximumWorkerContextPageEncodedBytes is the normative JSON response
	// boundary from Spec 047. It includes the trailing newline written by the
	// worker handler.
	MaximumWorkerContextPageEncodedBytes = 1 << 20
	MaximumWorkerContextPageItems        = 256
	MaximumWorkerContextCursorBytes      = 2048

	WorkerContextMessageKind  = "message"
	WorkerContextArtifactKind = "artifact"
)
View Source
const CloudWriteAuthorityMode = "cloud_v2_write"
View Source
const MaximumCursorPageBytes = 1 << 20

Variables

View Source
var (
	ErrAssertionInvalid     = errors.New("service assertion invalid")
	ErrAssertionSignature   = errors.New("service assertion signature invalid")
	ErrAssertionAudience    = errors.New("service assertion audience mismatch")
	ErrAssertionRoute       = errors.New("service assertion route mismatch")
	ErrAssertionDigest      = errors.New("service assertion request digest mismatch")
	ErrAssertionExpired     = errors.New("service assertion expired")
	ErrAssertionNotYetValid = errors.New("service assertion not yet valid")
	ErrAssertionReplay      = errors.New("service assertion replayed")
	ErrAssertionNonceStore  = errors.New("service assertion nonce store unavailable")
)
View Source
var (
	ErrScheduleClockNotMonotonic = errors.New("schedule tick clock is not monotonic")
	ErrScheduleTickBoundExceeded = errors.New("schedule tick bound exceeded")
)
View Source
var (
	ErrWorkerNotFound            = errors.New("worker not found")
	ErrWorkerRevoked             = errors.New("worker credential revoked")
	ErrWorkerNoCompatibleTarget  = errors.New("worker target is not compatible")
	ErrWorkerStaleLease          = errors.New("worker lease or fence is stale")
	ErrWorkerIdempotencyConflict = errors.New("worker idempotency key conflicts")
	ErrWorkerRequestInvalid      = errors.New("worker request is invalid")
	ErrWorkerArtifactIncomplete  = errors.New("worker artifact is incomplete")
)
View Source
var ErrAssertionConfiguration = errors.New("service assertion configuration invalid")
View Source
var ErrNoEligibleAgentOption = errors.New("no approved eligible Agent option")
View Source
var (
	ErrWorkerContextPageLimit = errors.New("worker context page exceeds payload limit")
)

Functions

func AccountIDFromContext

func AccountIDFromContext(ctx context.Context) (string, bool)

AccountIDFromContext returns the account authenticated by the signed fort-gateway assertion. Handlers must not read account identity from input.

func AgentCanonicalConversationHandler

func AgentCanonicalConversationHandler(repository AgentConversationReader) http.Handler

func AgentConversationCreateHandler

func AgentConversationCreateHandler(repository AgentConversationCreateRepository, clock func() time.Time) http.Handler

AgentConversationCreateHandler creates only a secondary Conversation. The verified account, stable Agent parent, identifiers, state, actor, and times are all allocated by the control plane rather than accepted from a client.

func AgentConversationMutationHandler

func AgentConversationMutationHandler(repository AgentConversationMutationRepository, clock func() time.Time) http.Handler

AgentConversationMutationHandler exposes one closed mutation vocabulary for secondary Conversations. Repositories enforce the canonical Home guard and the complete account -> Agent -> Conversation parent chain.

func AgentConversationProjectionHandler

func AgentConversationProjectionHandler(repository ReadAgentConversationRepository) http.Handler

AgentConversationProjectionHandler returns the complete durable projection for one Conversation only after verifying its stable Agent parent.

func AgentConversationTurnsHandler

func AgentConversationTurnsHandler(repository SendAgentTurnRepository, clock func() time.Time) http.Handler

AgentConversationTurnsHandler creates one direct human message, frozen context, Turn, and exact current-Agent target in the repository transaction.

func AgentConversationsHandler

func AgentConversationsHandler(repository AgentConversationReader) http.Handler

func AgentCreateHandler

func AgentCreateHandler(repository AgentCreateRepository, resolver AgentOptionResolver, clock func() time.Time) http.Handler

func AgentDetailHandler

func AgentDetailHandler(repository AgentReader) http.Handler

func AgentMutationHandler

func AgentMutationHandler(repository AgentMutationRepository, clock func() time.Time) http.Handler

func AgentRebindHandler

func AgentRebindHandler(repository AgentRebindRepository, resolver AgentOptionResolver, tokens RebindAcceptanceTokens, clock func() time.Time) http.Handler

func AgentTargetCancelHandler

func AgentTargetCancelHandler(repository CancelAgentTargetRepository, clock func() time.Time) http.Handler

AgentTargetCancelHandler durably requests cancellation for the exact target. The repository preserves its parent chain and accepted revision pins.

func AgentTargetRetryHandler

func AgentTargetRetryHandler(repository RetryAgentTargetRepository, clock func() time.Time) http.Handler

AgentTargetRetryHandler requeues the same exact target. The repository retains its original Behavior and Binding Revision pins.

func AgentsHandler

func AgentsHandler(repository AgentLister) http.Handler

func CloudWriteAuthorityActive

func CloudWriteAuthorityActive(getenv func(string) string) bool

CloudWriteAuthorityActive is the fail-closed deployment fence shared by owner commands and execution workers. Reads remain available in rollback mode, but no v2 mutation may reach Postgres until one exact positive epoch designates the cloud control plane as the sole write authority.

func CronHandler

func CronHandler(config CronHandlerConfig, provider ScheduleTickerProvider) http.Handler

CronHandler authenticates and runs one bounded tick. In legacy_v1_write rollback mode it remains authenticated but performs no database operation.

func CursorHandler

func CursorHandler(reader CursorReader) http.Handler

CursorHandler serves the bounded JSON half of the Node SSE reconnect loop.

func GroupCreateHandler

func GroupCreateHandler(repository GroupCreateRepository, clock func() time.Time) http.Handler

func GroupDetailHandler

func GroupDetailHandler(repository GroupDetailRepository) http.Handler

func GroupMembersHandler

func GroupMembersHandler(repository GroupMembersRepository, clock func() time.Time) http.Handler

GroupMembersHandler replaces the complete ordered stable-Agent membership. Behavior, Binding, participant, revision number, IDs, actor, and time are resolved by Fort and cannot be selected by the client.

func GroupMutationHandler

func GroupMutationHandler(repository GroupMutationRepository, clock func() time.Time) http.Handler

GroupMutationHandler exposes the closed presentation/state lifecycle for a stable Group. It never accepts membership or execution revision fields.

func GroupTurnsHandler

func GroupTurnsHandler(repository GroupTurnRepository, clock func() time.Time) http.Handler

func GroupsHandler

func GroupsHandler(repository GroupLister) http.Handler

func HandoffCancelHandler

func HandoffCancelHandler(repository HandoffCancelRepository, clock func() time.Time) http.Handler

func HandoffCreateHandler

func HandoffCreateHandler(repository HandoffCreateRepository, clock func() time.Time) http.Handler

func HandoffDetailHandler

func HandoffDetailHandler(repository HandoffDetailRepository) http.Handler

func HandoffsHandler

func HandoffsHandler(repository HandoffListRepository) http.Handler

func HealthHandler

func HealthHandler(info BuildInfo) http.Handler

HealthHandler reports only public deployment compatibility metadata.

func IssueServiceAssertion

func IssueServiceAssertion(key []byte, assertion ServiceAssertion) (string, error)

IssueServiceAssertion creates a compact HS256 assertion. The assertion key must contain at least 256 bits of secret material.

func RequireServiceAssertion

func RequireServiceAssertion(
	verifier ServiceAssertionVerifier,
	routeClass string,
	next http.Handler,
) http.Handler

RequireServiceAssertion bounds and digests the exact request body, verifies the gateway assertion, and injects only its signed account into context.

func RoutineMutationHandler

func RoutineMutationHandler(repository RoutineOwnerRepository, clock func() time.Time) http.Handler

func RoutineRunsHandler

func RoutineRunsHandler(repository RoutineOwnerRepository) http.Handler

RoutineRunsHandler exposes the durable attempt, lease, failure, next-action, and result history for one exact Agent-owned Routine.

func RoutineTestHandler

func RoutineTestHandler(repository RoutineOwnerRepository, clock func() time.Time) http.Handler

func RoutinesHandler

func RoutinesHandler(repository RoutineOwnerRepository, clock func() time.Time) http.Handler

RoutinesHandler lists or creates Agent-owned fort_cloud Routines. The stable Agent parent and current Behavior/Binding pins are always resolved by the server; the client supplies only Routine semantics and idempotency.

func WorkerHandler

func WorkerHandler(repository WorkerRepository, clock func() time.Time) http.Handler

WorkerHandler serves one bounded POST /api/v2/worker command. Machine authentication is intentionally independent from owner assertions and cron secrets, and completes before a request can invoke account-scoped work.

func WorkerOutputMessageRecordID

func WorkerOutputMessageRecordID(targetID, executionAttemptID string, fenceToken int64) string

WorkerOutputMessageRecordID binds a renderable output envelope to one exact target execution fence. Account identity is the remaining securebody scope component, so a stale or cross-account envelope cannot be replayed.

Types

type AgentConversationCreateRepository

type AgentConversationCreateRepository interface {
	CreateSecondaryConversation(context.Context, ledger.CreateSecondaryConversationCommand) (ledger.AgentConversationRecord, error)
}

type AgentConversationReader

type AgentConversationReader interface {
	ListAgentConversations(context.Context, string, string) ([]ledger.AgentConversationRecord, error)
}

type AgentCreateRepository

type AgentCreateRepository interface {
	CreateAgent(context.Context, ledger.CreateAgentCommand) (ledger.AgentRecord, error)
}

type AgentLifecycleCommandRepository

type AgentLifecycleCommandRepository interface {
	AgentCreateRepository
	AgentRebindRepository
}

type AgentLister

type AgentLister interface {
	ListAgents(context.Context, string, conversation.AgentState) ([]ledger.AgentRecord, error)
}

AgentLister is the read-only owner projection required by the v2 Agent roster. The account always comes from the verified gateway assertion.

type AgentMutationRepository

AgentMutationRepository is the owner-facing presentation/behavior seam. The handler can advance Fort-owned revisions but cannot select or alter any provider, model, machine, adapter, authority, policy, or source identity.

type AgentOptionResolver

type AgentOptionResolver interface {
	ResolveEligibleAgentOption(context.Context, string, string) (EligibleAgentOption, error)
}

func NoEligibleAgentOptions

func NoEligibleAgentOptions() AgentOptionResolver

NoEligibleAgentOptions is the production-safe default. Enrollment and Rebind remain unavailable until composition injects an approved inventory.

type AgentReader

type AgentReader interface {
	GetAgent(context.Context, string, string) (ledger.AgentRecord, error)
}

type BuildInfo

type BuildInfo struct {
	Commit         string
	SchemaVersion  string
	APIMinVersion  int
	APIMaxVersion  int
	AuthorityEpoch int64
	AuthorityMode  string
}

BuildInfo identifies the exact compatible deployment pair. AuthorityMode is intentionally explicit so clients never infer the write owner from reachability.

type CancelAgentTargetRepository

type CancelAgentTargetRepository interface {
	CancelAgentTarget(ctx context.Context, command ledger.CancelAgentTargetCommand) (ledger.AgentConversationTarget, error)
}

type CronHandlerConfig

type CronHandlerConfig struct {
	Secret        string
	AuthorityMode string
	AccountID     string
	SchedulerID   string
}

CronHandlerConfig contains no database-selected account input. AccountID is trusted server configuration for this single-account first release.

type CursorEvent

type CursorEvent struct {
	Cursor string `json:"cursor"`
	Kind   string `json:"kind"`
	Data   any    `json:"data"`
}

type CursorPage

type CursorPage struct {
	Events     []CursorEvent `json:"events"`
	NextCursor string        `json:"next_cursor"`
}

type CursorReader

type CursorReader interface {
	ReadCursorPage(context.Context, string, string) (CursorPage, error)
}

CursorReader returns durable events after one exact cursor. Implementations may long-poll, but must return before the bounded request context expires.

type EligibleAgentOption

type EligibleAgentOption struct {
	ID                       string                            `json:"id"`
	ExecutionSource          conversation.ExecutionSource      `json:"execution_source"`
	SourceAgent              conversation.SourceAgent          `json:"source_agent"`
	Binding                  conversation.AgentBindingRevision `json:"binding"`
	NonTransferableResources []ledger.RebindResource           `json:"non_transferable_resources"`
	ReadinessEvidence        []string                          `json:"readiness_evidence"`
	AuthorityEvidence        []string                          `json:"authority_evidence"`
}

EligibleAgentOption is server-held execution evidence selected by one opaque ID. Identity, revision, seat, and activation fields are deliberately absent from the option and are allocated by Fort for each command.

type EncryptedEnvelope

type EncryptedEnvelope struct {
	Ciphertext      []byte `json:"ciphertext"`
	KeyID           string `json:"key_id"`
	Nonce           []byte `json:"nonce"`
	Digest          string `json:"digest"`
	PlaintextLength int    `json:"plaintext_length"`
}

type GroupCreateRepository

type GroupCreateRepository interface {
	GetAgent(context.Context, string, string) (ledger.AgentRecord, error)
	CreateGroup(context.Context, ledger.CreateGroupCommand) (ledger.GroupRecord, error)
}

type GroupDetailRepository

type GroupDetailRepository interface {
	GetGroup(context.Context, string, string) (ledger.GroupRecord, error)
	ListGroupTurns(context.Context, string, string) ([]ledger.GroupTurnRecord, error)
	ListGroupMessages(context.Context, string, string) ([]ledger.AgentConversationMessage, error)
}

type GroupLister

type GroupLister interface {
	ListGroups(context.Context, string, conversation.ConversationState) ([]ledger.GroupRecord, error)
}

GroupLister is the minimal owner projection for the stable Group roster. Account identity always comes from a verified gateway assertion.

type GroupMembersRepository

type GroupMembersRepository interface {
	GetGroup(context.Context, string, string) (ledger.GroupRecord, error)
	GetAgent(context.Context, string, string) (ledger.AgentRecord, error)
	ReplaceGroupMembers(context.Context, ledger.ReplaceGroupMembersCommand) (ledger.GroupRecord, error)
}

type GroupMutationRepository

type GroupMutationRepository interface {
	RenameGroup(context.Context, ledger.RenameGroupCommand) (ledger.GroupRecord, error)
	SetGroupState(context.Context, ledger.SetGroupStateCommand) (ledger.GroupRecord, error)
}

type HandoffCancelRepository

type HandoffCancelRepository interface {
	CancelHandoff(context.Context, ledger.CancelHandoffCommand) (ledger.HandoffRecord, error)
}

type HandoffCreateRepository

type HandoffCreateRepository interface {
	CreateHumanHandoff(context.Context, ledger.CreateHumanHandoffCommand) (ledger.HandoffRecord, error)
}

type HandoffDetailRepository

type HandoffDetailRepository interface {
	GetHandoff(context.Context, string, string) (ledger.HandoffRecord, error)
}

type HandoffListRepository

type HandoffListRepository interface {
	ListHandoffs(context.Context, string) ([]ledger.HandoffRecord, error)
}

type HumanHandoffRepository

HumanHandoffRepository is the bounded owner-facing persistence contract. Execution identity and immutable revision evidence are resolved below this seam; handlers accept only human intent and an idempotency key.

type MachineCredential

type MachineCredential struct {
	AccountID string
	WorkerID  string
	MachineID string
	TokenHash string
	State     MachineCredentialState
}

MachineCredential is server-side enrollment evidence. TokenHash is the lowercase SHA-256 digest of a random bearer; raw machine tokens are never passed into the persistence layer.

type MachineCredentialState

type MachineCredentialState string
const (
	MachineCredentialEnrolled MachineCredentialState = "enrolled"
	MachineCredentialOffline  MachineCredentialState = "offline"
	MachineCredentialRevoked  MachineCredentialState = "revoked"
)

type NonceClaimer

type NonceClaimer interface {
	Claim(context.Context, string, string, string, time.Time) (bool, error)
}

NonceClaimer atomically records a nonce until the assertion expires. A production implementation must be durable and shared by all function instances; an in-memory implementation is not safe for deployment.

type ReadAgentConversationRepository

type ReadAgentConversationRepository interface {
	ReadAgentConversation(ctx context.Context, accountID, agentID, conversationID string) (ledger.AgentConversationProjection, error)
}

type RebindAcceptanceGrant

type RebindAcceptanceGrant struct {
	Audience  string                    `json:"aud"`
	Route     string                    `json:"route"`
	AccountID string                    `json:"account_id"`
	AgentID   string                    `json:"agent_id"`
	OptionID  string                    `json:"option_id"`
	Preview   ledger.AgentRebindPreview `json:"preview"`
	IssuedAt  time.Time                 `json:"issued_at"`
	ExpiresAt time.Time                 `json:"expires_at"`
}

RebindAcceptanceGrant is the complete server-issued disclosure accepted by the human. It is never decoded from an unsigned request body.

type RebindAcceptanceTokens

type RebindAcceptanceTokens interface {
	Issue(RebindAcceptanceGrant) (string, time.Time, error)
	Verify(string, time.Time) (RebindAcceptanceGrant, error)
}

func HMACRebindAcceptanceTokensFromEnvironment

func HMACRebindAcceptanceTokensFromEnvironment(getenv func(string) string) (RebindAcceptanceTokens, error)

HMACRebindAcceptanceTokensFromEnvironment loads the dedicated, server-only Rebind acceptance key. It intentionally does not fall back to assertion, body-encryption, or client-session key material.

func NewHMACRebindAcceptanceTokens

func NewHMACRebindAcceptanceTokens(key []byte, ttl time.Duration) (RebindAcceptanceTokens, error)

type RetryAgentTargetRepository

type RetryAgentTargetRepository interface {
	RetryAgentTarget(ctx context.Context, command ledger.RetryAgentTargetCommand) (ledger.AgentConversationTarget, error)
}

type RoutineOccurrence

type RoutineOccurrence struct {
	OccurrenceID      string
	RoutineID         string
	RoutineRevisionID string
	ScheduledFor      time.Time
	State             RoutineOccurrenceState
	IdempotencyKey    string
	RecordedAt        time.Time
}

RoutineOccurrence is the exact durable timestamp materialized by a tick. OccurrenceID and IdempotencyKey are deterministic functions of RoutineID and ScheduledFor, so recycled or overlapping functions converge on one row.

type RoutineOccurrenceState

type RoutineOccurrenceState string

RoutineOccurrenceState deliberately separates future materialization from work eligibility. Workers may claim only queued occurrences.

const (
	OccurrenceScheduled            RoutineOccurrenceState = "scheduled"
	OccurrenceQueued               RoutineOccurrenceState = "queued"
	OccurrenceMissedNeedsAttention RoutineOccurrenceState = "missed_needs_attention"
)

type RoutineSchedule

type RoutineSchedule struct {
	RoutineID         string
	RoutineRevisionID string
	Expression        string
	Timezone          string
	StartsAt          time.Time
}

RoutineSchedule is the immutable scheduling portion of one active fort_cloud Routine revision.

type ScheduleRepository

type ScheduleRepository interface {
	WithScheduleTick(context.Context, string, string, func(ScheduleTickTransaction) error) (acquired bool, err error)
}

ScheduleRepository provides one bounded, atomic schedule-tick transaction. A false acquired result means another invocation owns the advisory lock.

type ScheduleTickResult

type ScheduleTickResult struct {
	Status                 string    `json:"status"`
	TickID                 string    `json:"tick_id,omitempty"`
	Watermark              time.Time `json:"watermark,omitempty"`
	OccurrencesChanged     int       `json:"occurrences_changed"`
	InvalidRoutinesSkipped int       `json:"invalid_routines_skipped"`
	ExpiredLeasesRecovered int       `json:"expired_leases_recovered"`
	LateRoutineRunsExpired int       `json:"late_routine_runs_expired"`
}

ScheduleTickResult is safe operational metadata returned to Vercel Cron.

type ScheduleTickService

type ScheduleTickService struct {
	Repository ScheduleRepository
	Clock      func() time.Time
	TickIDs    func() string
}

ScheduleTickService deterministically expands six-field cron schedules inside a single repository transaction.

func (ScheduleTickService) Tick

func (service ScheduleTickService) Tick(ctx context.Context, accountID, schedulerID string) (ScheduleTickResult, error)

Tick performs exactly one bounded reconciliation and then returns.

type ScheduleTickTransaction

type ScheduleTickTransaction interface {
	Watermark(context.Context, string) (time.Time, bool, error)
	RecoverExpiredWorkerLeases(context.Context, time.Time, int) (int, error)
	ExpireLateRoutineRuns(context.Context, time.Time, int) (int, error)
	ActiveRoutineSchedules(context.Context, int) ([]RoutineSchedule, error)
	ApplyOccurrence(context.Context, RoutineOccurrence) (bool, error)
	SaveWatermark(context.Context, string, string, time.Time) error
}

ScheduleTickTransaction is an account-scoped database transaction holding both the advisory lock and the watermark row lock for one scheduler.

type ScheduleTicker

type ScheduleTicker interface {
	Tick(context.Context, string, string) (ScheduleTickResult, error)
}

ScheduleTicker is the narrow handler seam; it cannot run a provider or a permanent scheduler loop.

type ScheduleTickerProvider

type ScheduleTickerProvider func(context.Context) (ScheduleTicker, error)

ScheduleTickerProvider is invoked only after method, secret, authority mode, and static scope validation have succeeded.

type SendAgentTurnRepository

type SendAgentTurnRepository interface {
	SendAgentTurn(ctx context.Context, command ledger.SendAgentTurnCommand) (ledger.AgentTurnDispatch, error)
}

type ServiceAssertion

type ServiceAssertion struct {
	KeyID         string
	AccountID     string
	RouteClass    string
	Audience      string
	RequestDigest string
	IssuedAt      time.Time
	ExpiresAt     time.Time
	Nonce         string
}

ServiceAssertion is the short-lived, server-to-server identity envelope used between fort-gateway and fort-control. AccountID is derived by the gateway from its authenticated owner session and is never accepted from a client.

type ServiceAssertionVerifier

type ServiceAssertionVerifier struct {
	Audience  string
	Keys      map[string][]byte
	Clock     func() time.Time
	Nonces    NonceClaimer
	MaxTTL    time.Duration
	ClockSkew time.Duration
}

ServiceAssertionVerifier verifies signed gateway assertions and consumes their nonces exactly once.

func ServiceAssertionVerifierFromEnvironment

func ServiceAssertionVerifierFromEnvironment(
	getenv func(string) string,
	nonces NonceClaimer,
) (ServiceAssertionVerifier, error)

ServiceAssertionVerifierFromEnvironment loads the control-side verification key ring. The gateway carries one active signing key, while control may authenticate multiple explicitly configured keys during a bounded rotation.

func (ServiceAssertionVerifier) Verify

func (verifier ServiceAssertionVerifier) Verify(
	ctx context.Context,
	token string,
	routeClass string,
	requestDigest string,
) (ServiceAssertion, error)

Verify authenticates an assertion against the exact request route class and SHA-256 body digest, then atomically consumes its nonce.

type WorkerArtifact

type WorkerArtifact struct {
	ArtifactID              string                `json:"artifact_id"`
	ExecutionAttemptID      string                `json:"execution_attempt_id"`
	Kind                    string                `json:"kind"`
	State                   string                `json:"state"`
	ExpectedChunkCount      int                   `json:"expected_chunk_count"`
	ExpectedPlaintextLength int64                 `json:"expected_plaintext_length"`
	ExpectedEncodedLength   int64                 `json:"expected_encoded_length"`
	LogicalDigest           string                `json:"logical_digest"`
	EncryptionKeyID         string                `json:"encryption_key_id"`
	Chunks                  []WorkerArtifactChunk `json:"chunks"`
	CreatedAt               time.Time             `json:"created_at"`
	FinalizedAt             *time.Time            `json:"finalized_at,omitempty"`
	Created                 bool                  `json:"created"`
}

WorkerArtifact is the resumable upload projection returned to a worker. It deliberately contains manifest and receipt metadata only; encrypted chunk bodies remain private Postgres data and never inflate a status response.

type WorkerArtifactChunk

type WorkerArtifactChunk struct {
	ArtifactID          string    `json:"artifact_id"`
	ChunkIndex          int       `json:"chunk_index"`
	EncodedLength       int       `json:"encoded_length"`
	PlaintextLength     int       `json:"plaintext_length"`
	EncryptionKeyID     string    `json:"encryption_key_id"`
	AuthenticatedDigest string    `json:"authenticated_digest"`
	CreatedAt           time.Time `json:"created_at"`
	Created             bool      `json:"created"`
}

type WorkerArtifactChunkCommand

type WorkerArtifactChunkCommand struct {
	AccountID, WorkerID, MachineID, TargetID, ExecutionAttemptID, LeaseID string
	FenceToken                                                            int64
	IdempotencyKey, ArtifactID                                            string
	ChunkIndex                                                            int
	Plaintext                                                             []byte
	PlaintextDigest                                                       string
	// The remaining fields are populated only by the key-ring-enabled
	// repository after it encrypts Plaintext. They are never worker input.
	Ciphertext                     []byte
	EncodedLength, PlaintextLength int
	EncryptionKeyID                string
	Nonce                          []byte
	AuthenticatedDigest            string
	CreatedAt                      time.Time
}

type WorkerArtifactCreateCommand

type WorkerArtifactCreateCommand struct {
	AccountID, WorkerID, MachineID, TargetID, ExecutionAttemptID, LeaseID string
	FenceToken                                                            int64
	IdempotencyKey, ArtifactID                                            string
	ExpectedChunkCount                                                    int
	ExpectedPlaintextLength, ExpectedEncodedLength                        int64
	LogicalDigest, EncryptionKeyID                                        string
	CreatedAt                                                             time.Time
}

type WorkerArtifactFinalizeCommand

type WorkerArtifactFinalizeCommand struct {
	AccountID, WorkerID, MachineID, TargetID, ExecutionAttemptID, LeaseID string
	FenceToken                                                            int64
	IdempotencyKey, ArtifactID                                            string
	FinalizedAt                                                           time.Time
}

type WorkerArtifactStatusCommand

type WorkerArtifactStatusCommand struct {
	AccountID, WorkerID, MachineID, TargetID, ExecutionAttemptID, LeaseID string
	FenceToken                                                            int64
	IdempotencyKey, ArtifactID                                            string
	ObservedAt                                                            time.Time
}

type WorkerAssignment

type WorkerAssignment struct {
	TargetID                    string                   `json:"target_id"`
	TargetKind                  string                   `json:"target_kind"`
	OriginID                    string                   `json:"origin_id"`
	ExecutionAttemptID          string                   `json:"execution_attempt_id"`
	LeaseID                     string                   `json:"lease_id"`
	FenceToken                  int64                    `json:"fence_token"`
	WorkerID                    string                   `json:"worker_id"`
	MachineID                   string                   `json:"machine_id"`
	CapabilityRevisionID        string                   `json:"capability_revision_id"`
	Pins                        coreworker.ExecutionPins `json:"pins"`
	Execution                   WorkerExecutionBinding   `json:"execution"`
	ContextManifestID           string                   `json:"context_manifest_id"`
	Prompt                      string                   `json:"prompt"`
	OutputConversationID        string                   `json:"output_conversation_id"`
	OutputMessageKind           string                   `json:"output_message_kind"`
	OutputAuthorAgentID         string                   `json:"output_author_agent_id"`
	MaximumOutputPlaintextBytes int64                    `json:"maximum_output_plaintext_bytes"`
	InlineOutputPlaintextBytes  int64                    `json:"inline_output_plaintext_bytes"`
	// PromptEnvelope exists only between the key-ring-enabled repository and
	// its decryption boundary. It is never serialized to a worker.
	PromptEnvelope EncryptedEnvelope `json:"-"`
	ClaimedAt      time.Time         `json:"claimed_at"`
	ExpiresAt      time.Time         `json:"expires_at"`
	HardDeadline   time.Time         `json:"hard_deadline"`
}

type WorkerCancellationAck

type WorkerCancellationAck struct {
	AcknowledgementID  string    `json:"acknowledgement_id"`
	TargetID           string    `json:"target_id"`
	ExecutionAttemptID string    `json:"execution_attempt_id"`
	LeaseID            string    `json:"lease_id"`
	FenceToken         int64     `json:"fence_token"`
	AcknowledgedAt     time.Time `json:"acknowledged_at"`
}

type WorkerCancellationAckCommand

type WorkerCancellationAckCommand struct {
	AccountID          string
	WorkerID           string
	MachineID          string
	TargetID           string
	ExecutionAttemptID string
	LeaseID            string
	FenceToken         int64
	AcknowledgementID  string
	IdempotencyKey     string
	AcknowledgedAt     time.Time
}

type WorkerClaimCommand

type WorkerClaimCommand struct {
	AccountID            string
	WorkerID             string
	MachineID            string
	TargetID             string
	ExecutionAttemptID   string
	LeaseID              string
	IdempotencyKey       string
	CapabilityRevisionID string
	ClaimedAt            time.Time
	ExpiresAt            time.Time
}

type WorkerClaimNextCommand

type WorkerClaimNextCommand struct {
	AccountID            string
	WorkerID             string
	MachineID            string
	ExecutionAttemptID   string
	LeaseID              string
	IdempotencyKey       string
	CapabilityRevisionID string
	ClaimedAt            time.Time
	ExpiresAt            time.Time
}

WorkerClaimNextCommand asks the control plane to atomically select the oldest queued target whose immutable Binding is assigned to this exact worker and machine. Target selection remains server-side so a worker never guesses or scans account work.

type WorkerContextArtifactReference

type WorkerContextArtifactReference struct {
	ArtifactID              string    `json:"artifact_id"`
	Kind                    string    `json:"kind"`
	ExecutionAttemptID      string    `json:"execution_attempt_id"`
	ExpectedChunkCount      int       `json:"expected_chunk_count"`
	ExpectedPlaintextLength int64     `json:"expected_plaintext_length"`
	ExpectedEncodedLength   int64     `json:"expected_encoded_length"`
	LogicalDigest           string    `json:"logical_digest"`
	CreatedAt               time.Time `json:"created_at"`
	FinalizedAt             time.Time `json:"finalized_at"`
}

type WorkerContextItem

type WorkerContextItem struct {
	Kind     string                          `json:"kind"`
	Ordinal  int                             `json:"ordinal"`
	Message  *WorkerContextMessage           `json:"message,omitempty"`
	Artifact *WorkerContextArtifactReference `json:"artifact,omitempty"`
}

type WorkerContextMessage

type WorkerContextMessage struct {
	MessageID      int64     `json:"message_id"`
	ConversationID string    `json:"conversation_id"`
	TurnID         string    `json:"turn_id,omitempty"`
	TargetID       string    `json:"target_id,omitempty"`
	HandoffID      string    `json:"handoff_id,omitempty"`
	RoutineRunID   string    `json:"routine_run_id,omitempty"`
	MessageKind    string    `json:"message_kind"`
	AuthorKind     string    `json:"author_kind"`
	AuthorID       string    `json:"author_id"`
	AuthorAgentID  string    `json:"author_agent_id,omitempty"`
	Body           string    `json:"body"`
	CreatedAt      time.Time `json:"created_at"`
}

type WorkerContextPage

type WorkerContextPage struct {
	ContextManifestID string              `json:"context_manifest_id"`
	ManifestDigest    string              `json:"manifest_digest"`
	Items             []WorkerContextItem `json:"items"`
	NextCursor        string              `json:"next_cursor"`
}

WorkerContextPage contains only decrypted message content and immutable artifact references. Application AEAD keys, ciphertext, nonces, and raw artifact chunks are deliberately not represented by this transport type.

type WorkerContextPageCommand

type WorkerContextPageCommand struct {
	AccountID          string
	WorkerID           string
	MachineID          string
	TargetID           string
	ExecutionAttemptID string
	LeaseID            string
	FenceToken         int64
	IdempotencyKey     string
	Cursor             string
	ObservedAt         time.Time
}

WorkerContextPageCommand identifies one exact, actively fenced assignment. ContextManifestID is intentionally absent: the repository resolves the immutable manifest pinned by the target's Turn rather than trusting worker input.

type WorkerContextRepository

type WorkerContextRepository interface {
	ReadWorkerContextPage(context.Context, WorkerContextPageCommand) (WorkerContextPage, error)
}

WorkerContextRepository is kept separate from WorkerRepository so rollout remains additive: older endpoint fakes and adapters continue to satisfy the base machine-command contract, while context_page fails closed unless the backing repository explicitly implements this capability.

type WorkerExecutionBinding

type WorkerExecutionBinding struct {
	ExecutionSourceID         string          `json:"execution_source_id"`
	SourceAgentID             string          `json:"source_agent_id"`
	OpaqueSourceAgentID       string          `json:"opaque_source_agent_id"`
	FortProfile               string          `json:"fort_profile"`
	Provider                  string          `json:"provider"`
	RequestedModel            string          `json:"requested_model"`
	ResolvedModel             string          `json:"resolved_model"`
	AdapterID                 string          `json:"adapter_id"`
	AdapterRevision           string          `json:"adapter_revision"`
	SourceConfigDigest        string          `json:"source_config_digest"`
	AuthorityID               string          `json:"authority_id"`
	AuthorityRevision         string          `json:"authority_revision"`
	PolicyID                  string          `json:"policy_id"`
	PolicyRevision            string          `json:"policy_revision"`
	SessionBehavior           string          `json:"session_behavior"`
	MemoryBehavior            string          `json:"memory_behavior"`
	CapabilityEvidence        json.RawMessage `json:"capability_evidence"`
	ReadinessContractID       string          `json:"readiness_contract_id"`
	ReadinessContractRevision string          `json:"readiness_contract_revision"`
	Workdir                   string          `json:"workdir"`
	ComputerID                string          `json:"computer_id,omitempty"`
	CloudRuntime              string          `json:"cloud_runtime,omitempty"`
}

WorkerExecutionBinding is the immutable execution selector copied from the target's pinned Agent Binding Revision. It contains no provider credential, key material, or server-side application-encryption secret.

type WorkerLeaseHeartbeatCommand

type WorkerLeaseHeartbeatCommand struct {
	AccountID          string
	WorkerID           string
	MachineID          string
	TargetID           string
	ExecutionAttemptID string
	LeaseID            string
	FenceToken         int64
	IdempotencyKey     string
	ObservedAt         time.Time
	ExtendUntil        time.Time
}

type WorkerLeaseHeartbeatResult

type WorkerLeaseHeartbeatResult struct {
	TargetID           string                     `json:"target_id"`
	ExecutionAttemptID string                     `json:"execution_attempt_id"`
	LeaseID            string                     `json:"lease_id"`
	FenceToken         int64                      `json:"fence_token"`
	Directive          coreworker.WorkerDirective `json:"directive"`
	ExpiresAt          time.Time                  `json:"expires_at"`
}

type WorkerOutputReference

type WorkerOutputReference struct {
	ArtifactID string `json:"artifact_id"`
	Digest     string `json:"digest"`
}

type WorkerReadinessCommand

type WorkerReadinessCommand struct {
	AccountID            string
	WorkerID             string
	MachineID            string
	IdempotencyKey       string
	CapabilityRevisionID string
	Revision             int
	CapabilityEvidence   json.RawMessage
	EvidenceDigest       string
	ObservedAt           time.Time
}

type WorkerReadinessResult

type WorkerReadinessResult struct {
	Status               string    `json:"status"`
	CapabilityRevisionID string    `json:"capability_revision_id"`
	ObservedAt           time.Time `json:"observed_at"`
}

type WorkerRepository

WorkerRepository is the narrow server-side command seam. Implementations receive an already authenticated account/worker/machine identity and retain all atomic claim, lease, fence, and receipt rules inside the ledger adapter.

type WorkerTerminalCommand

type WorkerTerminalCommand struct {
	AccountID              string
	WorkerID               string
	MachineID              string
	TargetID               string
	ExecutionAttemptID     string
	LeaseID                string
	FenceToken             int64
	TerminalReceiptID      string
	IdempotencyKey         string
	Status                 coreworker.TerminalStatus
	ReceiptPlaintext       json.RawMessage
	OutputMessagePlaintext *string
	// Receipt and OutputMessage are populated only by the key-ring-enabled
	// repository. Authenticated workers submit bounded plaintext over TLS and
	// never receive or use the application AEAD key.
	Receipt       EncryptedEnvelope
	Output        WorkerOutputReference
	OutputMessage *EncryptedEnvelope
	CommittedAt   time.Time
}

type WorkerTerminalResult

type WorkerTerminalResult struct {
	TargetID           string                    `json:"target_id"`
	ExecutionAttemptID string                    `json:"execution_attempt_id"`
	LeaseID            string                    `json:"lease_id"`
	FenceToken         int64                     `json:"fence_token"`
	TerminalReceiptID  string                    `json:"terminal_receipt_id"`
	Status             coreworker.TerminalStatus `json:"status"`
	Output             WorkerOutputReference     `json:"output"`
	MessageID          int64                     `json:"message_id,omitempty"`
	CommittedAt        time.Time                 `json:"committed_at"`
	Created            bool                      `json:"created"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL