Documentation
¶
Overview ¶
Package control defines Rainier's public control-plane application contract: the portable domain vocabulary, the caller-facing application interfaces, and the narrow host-supplied ports that self-hosted controld and Rainier Cloud both consume. Its canonical import path is github.com/tokencanopy/rainier/control.
The package is a contract, not a service. It contains no implementation of the lifecycle, scheduling, reconciliation, or attach behavior: it freezes the seam those behaviors will be extracted behind, and pins it with external-package contract tests so the behaviors can be moved out of internal/controld by later workers without editing this surface.
The package is neutral in four ways, each a hard boundary:
- Transport-neutral: it defines no HTTP handler, WebSocket route, SQL statement, or wire frame. Adapters map these sentinels and commands to a concrete transport.
- Identity-neutral: it carries no role, email, GitHub account, or membership record. Actors are opaque IDs produced by a host adapter, never decoded from client JSON.
- Persistence-neutral: repository ports expose only the semantic reads and transitions the existing application behavior needs. They never expose SQL transactions, rows, JSON blobs, credentials, secrets, user records, or provider resources.
- Provider-neutral: no GCP project, AWS account, Azure subscription, machine type, cluster, native zone, or disk ID appears anywhere in the package. Placement is expressed in Rainier execution modes, product regions, portable capabilities, and opaque pool and runner identities.
Terminal and workspace bytes remain the already-public protocol packages (github.com/tokencanopy/rainier/protocol/{terminal,runner,workspace}). This package references those contracts but never duplicates their message structs.
Compatibility ¶
This surface is pre-v1 and may evolve during /v0/, but there is one canonical contract at a time: no V2, Legacy, compatibility-alias, or Cloud-fork type exists here. Later workers may consume this package but must not edit its exported signatures; a change to the contract is a coordinated decision, not a per-lane convenience.
Index ¶
- Variables
- type Action
- type Actor
- type ActorID
- type ActorKind
- type Application
- type AttachTarget
- type AttachTerminal
- type AttachmentBroker
- type AttachmentMode
- type Attachments
- type Authorizer
- type Checkpoint
- type CheckpointLocation
- type CheckpointLocator
- type Clock
- type Connector
- type CreateEnvironment
- type CreateSession
- type DeleteEnvironment
- type DeleteSession
- type Environment
- type EnvironmentID
- type EnvironmentPage
- type EnvironmentQuery
- type EnvironmentRepository
- type Environments
- type Event
- type EventID
- type EventRecorder
- type ExecutionMode
- type Fleet
- type FleetRepository
- type IDGenerator
- type PlacementScope
- type Pool
- type PoolID
- type PoolResolver
- type PortableSpec
- type PullWorkspace
- type PushWorkspace
- type ReconcileResult
- type RepoRef
- type Requirements
- type Resource
- type ResourceKind
- type ResumeSession
- type Runner
- type RunnerEvent
- type RunnerID
- type RunnerPage
- type RunnerQuery
- type RunnerRegistration
- type RunnerRegistrationResult
- type RunnerSession
- type RunnerSnapshot
- type RunnerTransport
- type Scope
- type Session
- type SessionID
- type SessionPage
- type SessionQuery
- type SessionRepository
- type SessionState
- type Sessions
- type SnapshotSession
- type SuspendSession
- type TerminalStream
- type TransitionOpts
- type UnitOfWork
- type UpdateEnvironment
- type Usage
- type WorkspaceDiff
- type WorkspaceID
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalid reports a command or scope that is malformed: an empty or // unknown ID, an unknown actor kind or execution mode, a scope missing // its hosted region or cell, or a contradictory create (an environment // and a scratch spec together). It is the one non-disclosing answer for // input that cannot be authorized against anything. ErrInvalid = errors.New("control: invalid") // ErrDenied reports that the current authorizer refused the operation. // The resource may or may not exist; ErrDenied does not say which. ErrDenied = errors.New("control: denied") // ErrNotFound reports a lookup that found nothing. It is also the // non-disclosing answer for a resource outside the authoritative // workspace: a caller asking about another workspace's session learns // "not found", never "that workspace exists and has this session". ErrNotFound = errors.New("control: not found") // ErrConflict reports a guarded transition whose current state was not in // the allowed from-list, a name already held, or a contradictory request. ErrConflict = errors.New("control: conflict") // ErrStale reports an operation whose authoritative generation or setup // hash no longer matches the resource's current one: a runner event from // a superseded placement generation, or a snapshot built from an edited // environment. ErrStale = errors.New("control: stale") // runner with no control connection, a store that cannot answer. ErrUnavailable = errors.New("control: unavailable") // ErrUnsupported reports an operation or capability the current build // does not implement. ErrUnsupported = errors.New("control: unsupported") )
The closed error set of the control contract. Every operation in this package reports failure through one of these seven sentinels; ports may wrap a sentinel with safe context but must not surface SQL, credentials, provider responses, filesystem paths, terminal output, or session content in that context. Callers branch with errors.Is and never inspect the wrapped message text.
HTTP adapters map these centrally to status codes; this package carries no status code and no public error-envelope text.
var NonTerminal = []SessionState{StateQueued, StateCreating, StateRunning, StateSuspendedWarm, StateSuspendedCold}
NonTerminal lists every non-terminal state, in the order a session normally progresses through them. Callers pass it as the from-list of a guarded transition when any live state should be accepted.
Functions ¶
This section is empty.
Types ¶
type Action ¶
type Action string
Action is the closed action vocabulary of the frozen application operations. The action and the resource kind together name an operation the Authorizer may allow or deny.
const ( ActionCreate Action = "create" ActionGet Action = "get" ActionList Action = "list" ActionUpdate Action = "update" ActionDelete Action = "delete" ActionSuspend Action = "suspend" ActionResume Action = "resume" ActionSnapshot Action = "snapshot" ActionAttach Action = "attach" ActionDiff Action = "diff" ActionPush Action = "push" ActionPull Action = "pull" )
type Actor ¶
Actor is an authenticated principal. It is deliberately identity-only: it carries no role, email, or membership record, and no cached allow/deny decision. Current authorization is always an Authorizer call against the surrounding Scope.
type ActorID ¶
type ActorID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type ActorKind ¶
type ActorKind string
ActorKind names the two kinds of principal an operation may run as. An actor is authoritative adapter output: the host constructs it from authenticated state, never by decoding a client-supplied field from JSON.
type Application ¶
type Application interface {
Sessions
Environments
Fleet
Attachments
}
Application is the whole caller-facing application contract. It embeds the four operation-oriented interfaces and nothing else, so a consumer depends on the behaviors it uses rather than on a concrete service type.
type AttachTarget ¶
type AttachTarget struct {
WorkspaceID WorkspaceID
SessionID SessionID
PoolID PoolID
RunnerID RunnerID
PlacementGeneration uint64
ControllerGeneration uint64
}
AttachTarget is the fully resolved binding an AttachmentBroker needs to splice a stream to a session: the workspace, session, pool, runner, and the placement and controller generations the application granted.
type AttachTerminal ¶
type AttachTerminal struct {
SessionID SessionID
Since uint64
Mode AttachmentMode
}
AttachTerminal is the command for AttachTerminal. Since is the attach cursor (terminal.SinceAll for the whole log, 0 for a snapshot of the current screen). Mode distinguishes viewer from controller intent.
type AttachmentBroker ¶
type AttachmentBroker interface {
Attach(ctx context.Context, target AttachTarget, stream TerminalStream) error
}
AttachmentBroker splices a terminal stream onto a session, given a fully resolved AttachTarget. The granted controller generation arrives out of band; the broker never changes terminal JSON.
type AttachmentMode ¶
type AttachmentMode string
AttachmentMode names the intent of an attach: a viewer reads a session's terminal; a controller also writes to it. Controller authorization and the monotonic controller-lease generation are application facts — the AttachmentBroker receives the granted generation out of band rather than changing the terminal protocol.
const ( AttachmentViewer AttachmentMode = "viewer" AttachmentController AttachmentMode = "controller" )
type Attachments ¶
type Attachments interface {
AttachTerminal(context.Context, Scope, AttachTerminal, TerminalStream) error
WorkspaceDiff(context.Context, Scope, WorkspaceDiff) (workspace.DiffAnswer, error)
PushWorkspace(context.Context, Scope, PushWorkspace) error
PullWorkspace(context.Context, Scope, PullWorkspace) error
}
Attachments is the attach/workspace half of the caller-facing application contract. Terminal and workspace bytes use the public protocol packages; this interface references them and never duplicates their message structs.
type Authorizer ¶
Authorizer is the current authorization authority. The application invokes it before any state disclosure or side effect; self-hosted and Cloud supply different policy adapters behind the same signature.
type Checkpoint ¶
Checkpoint is a portable opaque reference to a session snapshot, plus its format and capability metadata. The provider object or image reference behind Ref stays inside the checkpoint adapter; this type never names it.
type CheckpointLocation ¶
CheckpointLocation is where a checkpoint can be booted: on any runner of the pool (Portable), or only on the named ones. Both empty means nowhere — the checkpoint is not usable right now and the caller boots without it.
type CheckpointLocator ¶
type CheckpointLocator interface {
LocateCheckpoint(ctx context.Context, ws WorkspaceID, cp Checkpoint) (CheckpointLocation, error)
}
CheckpointLocator is the host's knowledge of where checkpoint artifacts live. Self-hosted snapshots are container images on the runner that built them; hosted checkpoints are regional objects any capable runner restores. The application asks and never assumes.
type Connector ¶
type Connector struct {
Type string
Raw json.RawMessage
}
Connector is one declared attachment of an environment, treated opaquely by the control model: Type is the connector kind, and Raw is the original object verbatim. Adapters bound and validate connector payloads (the control model does not know GitHub token storage, file paths, or tunnel targets).
type CreateEnvironment ¶
type CreateEnvironment struct {
Name string
Image string
Setup string
Init string
InitTimeoutSec int
EgressAllow []string
SecretRefs []string
Connectors []Connector
Requirements Requirements
SetupTimeoutSec int
}
CreateEnvironment is the command for CreateEnvironment.
type CreateSession ¶
type CreateSession struct {
Name string
EnvironmentID EnvironmentID
Spec PortableSpec
Repos []RepoRef
IdempotencyKey string
}
CreateSession is the command for CreateSession. EnvironmentID names the environment the session starts from, or is empty for a scratch session; Spec is the session's own execution description, layered over that environment by the rules on PortableSpec. No combination of the two is contradictory: a session that names an environment may still choose its command, override its image, or reach more hosts, and a scratch session that names no image asks the host for its default one. A host that wants to forbid an override, or require an image, does so in its own policy — this contract says what is possible, not what a given host allows.
Repos overrides the repositories the environment's connectors declare. Its nil-vs-empty distinction is load-bearing: nil means "the caller said nothing, inherit the environment's connectors"; a non-nil empty slice means "clone nothing"; a non-empty slice means "clone exactly these, in order".
It does not accept CPU, memory, a VM shape, or a user-selected size: environment defaults and host policy derive Requirements, so an ordinary session is created without any sizing choice.
func (CreateSession) Validate ¶
func (c CreateSession) Validate() error
Validate reports whether c is well formed. It returns ErrInvalid for a repository reference that names no repository. No combination of EnvironmentID and Spec is refused, because none is contradictory (see PortableSpec).
type DeleteEnvironment ¶
type DeleteEnvironment struct {
ID EnvironmentID
}
DeleteEnvironment is the command for DeleteEnvironment.
type DeleteSession ¶
type DeleteSession struct {
ID SessionID
}
DeleteSession is the command for DeleteSession.
type Environment ¶
type Environment struct {
ID EnvironmentID
WorkspaceID WorkspaceID
Name string
Image string
Setup string
SetupHash string // identity of the build inputs (image + setup)
Init string // per-boot hook, run after setup and clone
InitTimeoutSec int
EgressAllow []string
SecretRefs []string // secret names; the control model never carries a value
Connectors []Connector
Requirements Requirements
SetupTimeoutSec int
// Snapshot is the cached checkpoint built from this environment's setup,
// if one exists. SnapshotHash records which SetupHash it was built from;
// a snapshot whose hash no longer matches the environment's is stale.
Snapshot Checkpoint
SnapshotHash string
CreatedAt time.Time
UpdatedAt time.Time
}
Environment is a named, reusable template a session starts from, as the application service sees it: image, setup and init scripts, egress hosts, secret references (names only, never values), connectors, portable requirements, checkpoint metadata, and timestamps. It names no provider, machine shape, or size.
type EnvironmentID ¶
type EnvironmentID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type EnvironmentPage ¶
type EnvironmentPage struct {
Environments []Environment
NextCursor string
}
EnvironmentPage is one page of ListEnvironments. NextCursor is empty on the last page.
type EnvironmentQuery ¶
EnvironmentQuery filters and paginates ListEnvironments. Limit is capped by the implementation, Cursor is opaque, and rows come back in stable (name, id) order.
type EnvironmentRepository ¶
type EnvironmentRepository interface {
CreateEnvironment(ctx context.Context, ws WorkspaceID, e Environment) (Environment, error)
GetEnvironment(ctx context.Context, ws WorkspaceID, id EnvironmentID) (Environment, error)
ListEnvironments(ctx context.Context, ws WorkspaceID, q EnvironmentQuery) ([]Environment, string, error)
UpdateEnvironment(ctx context.Context, ws WorkspaceID, e Environment) (Environment, error)
DeleteEnvironment(ctx context.Context, ws WorkspaceID, id EnvironmentID) error
// CountSessionsByEnvironment counts sessions on envID whose state is in
// states; an empty states counts every session on the environment.
CountSessionsByEnvironment(ctx context.Context, ws WorkspaceID, envID EnvironmentID, states []SessionState) (int, error)
// SetEnvironmentSnapshot records a built snapshot against the environment
// only while its SetupHash still equals expectHash; otherwise it changes
// nothing and reports a stale/conflict outcome. ErrStale when SetupHash no
// longer equals expectHash, ErrNotFound when envID does not exist in ws.
SetEnvironmentSnapshot(ctx context.Context, ws WorkspaceID, envID EnvironmentID, expectHash, ref string, runnerID RunnerID) error
}
EnvironmentRepository is the workspace-keyed environment persistence port, mapped from internal/controld.Store:
CreateEnvironment → Store.CreateEnvironment GetEnvironment → Store.GetEnvironment ListEnvironments → Store.ListEnvironments UpdateEnvironment → Store.UpdateEnvironment DeleteEnvironment → Store.DeleteEnvironment CountSessionsByEnvironment → Store.CountSessionsByEnvironment SetEnvironmentSnapshot → Store.SetEnvironmentSnapshot
type Environments ¶
type Environments interface {
CreateEnvironment(context.Context, Scope, CreateEnvironment) (Environment, error)
GetEnvironment(context.Context, Scope, EnvironmentID) (Environment, error)
ListEnvironments(context.Context, Scope, EnvironmentQuery) (EnvironmentPage, error)
UpdateEnvironment(context.Context, Scope, UpdateEnvironment) (Environment, error)
DeleteEnvironment(context.Context, Scope, DeleteEnvironment) error
}
Environments is the environment half of the caller-facing application contract.
type Event ¶
type Event struct {
ID EventID
WorkspaceID WorkspaceID
ActorID ActorID
Action Action
Resource Resource
At time.Time
Usage Usage
// PlacementGeneration is the session placement generation an event about
// a session happened under, so usage is attributed to exactly one
// generation; zero for an event about any other resource.
PlacementGeneration uint64
}
Event is a fixed-field, provider-neutral application fact: its own stable event ID, the workspace and actor it happened for, the resource it touched and the action taken, the timestamp, and optional usage facts. It has no terminal data, conversation content, secret, raw error, price, or provider resource ID.
type EventID ¶
type EventID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type EventRecorder ¶
EventRecorder records one application event. It is deliberately a semantic port: the later persistence/outbox plan makes mutation plus event atomic without changing the event vocabulary.
type ExecutionMode ¶
type ExecutionMode string
ExecutionMode names the three Rainier execution products. It is a Rainier concept, not a provider one: dedicated and serverless both hide their provider underneath, and self_hosted names an installation the customer runs from the OSS repository.
const ( // ExecutionSelfHosted is a customer-operated installation. ExecutionSelfHosted ExecutionMode = "self_hosted" // ExecutionDedicated is a Rainier-managed workspace-exclusive execution // plane. ExecutionDedicated ExecutionMode = "dedicated" // ExecutionServerless is Rainier-managed shared capacity with a hardened // sandbox per session. ExecutionServerless ExecutionMode = "serverless" )
type Fleet ¶
type Fleet interface {
RegisterRunner(context.Context, RunnerRegistration) (RunnerRegistrationResult, error)
ReconcileRunner(context.Context, RunnerSnapshot) (ReconcileResult, error)
ApplyRunnerEvent(context.Context, RunnerEvent) error
ListRunners(context.Context, Scope, RunnerQuery) (RunnerPage, error)
}
Fleet is the fleet half of the caller-facing application contract. The first three methods are service-principal calls: they carry authoritative bindings in their payload and never accept a user-created Scope. ListRunners is an ordinary scoped query.
type FleetRepository ¶
type FleetRepository interface {
// UpsertRunner stores r as pool's view of that runner. ErrStale when
// r.Generation is below the runner's stored generation; nothing changes.
UpsertRunner(ctx context.Context, pool PoolID, r Runner) error
SetRunnerConnected(ctx context.Context, pool PoolID, id RunnerID, connected bool) error
ListRunners(ctx context.Context, pool PoolID) ([]Runner, error)
// SessionsOnRunner returns the sessions in states placed on id within pool.
SessionsOnRunner(ctx context.Context, pool PoolID, id RunnerID, states []SessionState) ([]Session, error)
// OldestQueued returns the queued sessions of pool, oldest first.
OldestQueued(ctx context.Context, pool PoolID) ([]Session, error)
}
FleetRepository is the pool-keyed runner/capacity persistence port, mapped from internal/controld.Store:
UpsertRunner → Store.UpsertRunner SetRunnerConnected → Store.SetRunnerConnected ListRunners → Store.ListRunners SessionsOnRunner → Store.SessionsOnRunner (capacity math, reconciliation) OldestQueued → Store.OldestQueued (placement pass)
type IDGenerator ¶
type IDGenerator interface {
NewSessionID() SessionID
NewEnvironmentID() EnvironmentID
NewEventID() EventID
}
IDGenerator mints the three identities the application allocates. Adapters may prefix, namespace, or verify uniqueness; the application only requires that returned IDs are non-empty and distinct.
type PlacementScope ¶
type PlacementScope struct {
ProductRegion string
HomeCell string
Mode ExecutionMode
}
PlacementScope is the Rainier placement context of a call: which product region the workspace lives in, which cell is its home, and which execution mode it runs under. It is authoritative adapter output — the host derives it from current authoritative records, and the client cannot supply or override it.
For a self-hosted installation the region and cell are the documented installation-local values ("self-hosted" and "default" are typical), not a real cloud region.
type Pool ¶
Pool is an opaque eligible scheduling boundary with aggregate capacity and capabilities. The pool resolver may change providers without changing a session request; the application selects among runners inside one pool.
type PoolID ¶
type PoolID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type PoolResolver ¶
PoolResolver owns product/provider policy: it returns the eligible pools for a session's requirements. The application owns selection among the eligible runners inside the chosen pool.
type PortableSpec ¶
PortableSpec is the resolved, provider-neutral execution description of a session: what image to boot, what command to run, which egress hosts it may reach, and which repositories to clone. It names no VM shape, no size, and no provider resource.
On a CreateSession it is the session's own description, layered over the environment the create names, if any. An environment is a template and a session is an instance of it: every field that is set overrides the environment's, and every field that is unset is inherited. Unset is "" for Image and nil for a list; an explicitly empty list means "none".
Image unset: the environment's image — its current snapshot when
one is valid — or, on a scratch session, the host's default
image. Set: this image, and no snapshot reuse for this
session, because a snapshot is built from the environment's
own image and setup.
Cmd unset: the image's default command. Set: this command. An
environment carries no command; this is how a session from
one says what to run.
EgressAllow unset: the environment's list. Set: the environment's list
extended by these hosts, in order, without duplicates. An
environment's egress is what it needs to work; a session
adds to it and never silently removes from it.
Repos the repository override; see CreateSession.Repos.
type PullWorkspace ¶
PullWorkspace is the command for PullWorkspace: stream the gzipped tar archive of Path out of the session's workspace into Body.
type PushWorkspace ¶
PushWorkspace is the command for PushWorkspace: stream the gzipped tar archive at Body into Path inside the session's workspace. Body is bounded by the public workspace limits; no second archive or path type is introduced.
type ReconcileResult ¶
type ReconcileResult struct {
// Generation is the generation now authoritative for this runner.
Generation uint64
// Fenced reports whether the snapshot lost to a newer generation and the
// runner must stop acting on older authority.
Fenced bool
// Destroy names sessions the store has no live record of on this runner;
// the runner must tear them down as orphans.
Destroy []SessionID
}
ReconcileResult is the application's answer to a snapshot.
type RepoRef ¶
RepoRef is one entry of a session's repository override, in the spelling the caller sent: "owner/name" plus the branch to clone from. It is the request shape, not the resolved clone instruction (that lives in the public runner protocol). An empty BaseBranch means the default branch.
type Requirements ¶
type Requirements struct {
Capabilities []string // portable runtime capabilities, e.g. "gpu"
MinCPU int64 // whole vCPU units; 0 = unspecified
MinMemoryBytes int64 // 0 = unspecified
MinDiskBytes int64 // 0 = unspecified
}
Requirements is the portable capability-and-resource ask a session (or its environment) makes of the pool that will run it. It names portable capabilities and resource minima; it has no provider SKU, machine type, or user-selected size. Session sizing stays optional and automatic for clients — environment defaults and host policy derive Requirements.
type Resource ¶
type Resource struct {
Kind ResourceKind
WorkspaceID WorkspaceID
ID string // the resource's opaque identifier
CreatorID ActorID
}
Resource names the resource an authorization decision is about: its kind, its authoritative workspace, its opaque ID, and its creator when the resource has one. It carries no role — roles are the adapter's to interpret, never a field here.
type ResourceKind ¶
type ResourceKind string
ResourceKind is the closed resource-kind vocabulary of the frozen application operations.
const ( ResourceSession ResourceKind = "session" ResourceEnvironment ResourceKind = "environment" ResourceRunner ResourceKind = "runner" )
type ResumeSession ¶
type ResumeSession struct {
ID SessionID
}
ResumeSession is the command for ResumeSession.
type Runner ¶
type Runner struct {
ID RunnerID
PoolID PoolID
CapacityUsed int
CapacityTotal int
Connected bool
// Generation is monotonic per runner; a stale holder is rejected without
// replacing the event shapes (see RunnerEvent).
Generation uint64
Capabilities []string
LastSeenAt time.Time
}
Runner is a registered fleet member within a pool and its current capacity. Identity and generation are opaque Rainier identities; provider identity stays in adapters.
type RunnerEvent ¶
type RunnerEvent struct {
WorkspaceID WorkspaceID
PoolID PoolID
RunnerID RunnerID
Generation uint64
SessionID SessionID
State SessionState
Detail string
ChildExitCode *int
// PlacementGeneration is the session placement generation the runner
// was given when the sandbox was created, echoed back so a report from a
// stale sandbox is fenced by the session's own authority and not only by
// the connection it arrived on. Zero means "not carried" (an old runner)
// and fences nothing.
PlacementGeneration uint64
}
RunnerEvent is one unsolicited lifecycle report a runner makes about a session it holds. It carries its own authoritative workspace, pool, runner, and generation bindings; an event that does not match the authoritative workspace, pool, runner, or generation is stale and ignored. State is the lifecycle state the event reports; Detail is the runner's own sentence (failure tail, snapshot ref); ChildExitCode is set for a child exit.
type RunnerID ¶
type RunnerID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type RunnerPage ¶
RunnerPage is one page of ListRunners. NextCursor is empty on the last page.
type RunnerQuery ¶
RunnerQuery filters and paginates ListRunners. Limit is capped by the implementation, Cursor is opaque, and rows come back in stable (id) order.
type RunnerRegistration ¶
type RunnerRegistration struct {
WorkspaceID WorkspaceID
PoolID PoolID
RunnerID RunnerID
Generation uint64
CapacityUsed int
CapacityTotal int
Capabilities []string
Sessions []RunnerSession
}
RunnerRegistration is a runner's registration claim. Fleet service-principal calls carry their authoritative workspace, pool, runner, and session bindings here rather than accepting a user-created Scope. Every field is adapter-derived; none is decoded directly from client JSON.
type RunnerRegistrationResult ¶
type RunnerRegistrationResult struct {
// Accepted reports whether the registration took effect. A stale
// generation is refused rather than recorded.
Accepted bool
// Generation is the generation now authoritative for this runner.
Generation uint64
}
RunnerRegistrationResult is the application's answer to a registration.
type RunnerSession ¶
type RunnerSession struct {
SessionID SessionID
State SessionState
}
RunnerSession is one session a runner reports it holds, for registration and reconciliation.
type RunnerSnapshot ¶
type RunnerSnapshot struct {
WorkspaceID WorkspaceID
PoolID PoolID
RunnerID RunnerID
Generation uint64
CapacityUsed int
CapacityTotal int
Sessions []RunnerSession
}
RunnerSnapshot is a runner's authoritative current-state report for reconciliation: its identity, generation, capacity, and the sessions it holds.
type RunnerTransport ¶
type RunnerTransport interface {
Dispatch(ctx context.Context, pool PoolID, id RunnerID, m runner.ToRunner) (runner.FromRunner, error)
Connected(pool PoolID, id RunnerID) bool
}
RunnerTransport dispatches commands to a runner and reports connectivity. Dispatch carries the public runner protocol as-is; transport authentication and connection ownership stay in adapters.
type Scope ¶
type Scope struct {
WorkspaceID WorkspaceID
Actor Actor
Placement PlacementScope
}
Scope is the authoritative context every hosted application command and query receives. It carries the workspace and actor the call is authorized as, plus the placement context. It contains no role and no cached allow/deny decision: the Authorizer is the current authority, invoked against this scope before any state disclosure or side effect.
func (Scope) Validate ¶
Validate reports whether s is a usable scope. A zero Scope is invalid; so is one with an empty workspace or actor ID, an unknown actor kind, an unknown execution mode, or a missing product region or home cell. It returns ErrInvalid for every rejection, and never a free-form message.
type Session ¶
type Session struct {
ID SessionID
WorkspaceID WorkspaceID
CreatorID ActorID
Name string
State SessionState
EnvironmentID EnvironmentID // "" for a scratch session
Spec PortableSpec // the resolved execution description
SetupHash string // identity of the setup script actually dispatched; "" when none
PoolID PoolID
RunnerID RunnerID
// PlacementGeneration is the monotonic generation of this session's
// current placement. Later hosted fencing rejects a runner event whose
// generation does not match, without replacing the event shape. A
// repository advances it by one on every Transition whose RunnerID option
// names a runner, and leaves it unchanged otherwise. A generation is one
// sandbox on one runner: the scheduler's placement, reconcile's adoption,
// and a cold resume — which names the row's own runner, because it starts
// a new sandbox there — each open one; a warm resume unpauses the sandbox
// it has and opens none.
PlacementGeneration uint64
// ControllerGeneration is the monotonic generation of this session's
// current terminal controller: 0 until a controller has attached, then
// the value NextControllerGeneration last returned. A viewer attaches
// under the current value; a controller advances it. Stale input is
// fenced against it by the attachment plane.
ControllerGeneration uint64
IdempotencyKey string
ChildExitCode *int
Error string
CreatedAt time.Time
UpdatedAt time.Time
LastEventAt time.Time
}
Session is one coding-agent run as the application service sees it: its identity, workspace, creator, lifecycle state, resolved portable execution spec, selected pool and runner, monotonic placement generation, idempotency key, exit code, and timestamps. It carries no role, email, provider, native machine shape, charge, or credential.
type SessionID ¶
type SessionID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.
type SessionPage ¶
SessionPage is one page of ListSessions. NextCursor is empty on the last page.
type SessionQuery ¶
SessionQuery filters and paginates ListSessions. Limit is capped by the implementation; Cursor is opaque to callers; rows come back in stable (created_at, id) order; and IncludeTerminal admits the terminal states that the default list hides. There is no provider filter: a query cannot name a provider, machine type, zone, or native resource.
type SessionRepository ¶
type SessionRepository interface {
// CreateSession stores s and returns the stored row. ErrConflict when the
// name is already held by another non-terminal session of the same
// creator; a replayed idempotency key returns the existing row.
CreateSession(ctx context.Context, ws WorkspaceID, s Session) (Session, error)
GetSession(ctx context.Context, ws WorkspaceID, id SessionID) (Session, error)
// SessionByIDem returns the session a creator already created under key.
SessionByIDem(ctx context.Context, ws WorkspaceID, creator ActorID, key string) (Session, error)
// ListSessions returns one page and the opaque next cursor ("" at the
// end).
ListSessions(ctx context.Context, ws WorkspaceID, q SessionQuery) ([]Session, string, error)
// Transition moves id from any state in from to to, optionally updating
// the transition columns. ErrConflict when the current state is not in
// from; ErrNotFound when id does not exist. When opts.RunnerID names a
// runner the repository also advances PlacementGeneration (see Session).
Transition(ctx context.Context, ws WorkspaceID, id SessionID, from []SessionState, to SessionState, opts TransitionOpts) error
// SetSessionSetupHash records the setup a session was dispatched with.
SetSessionSetupHash(ctx context.Context, ws WorkspaceID, id SessionID, hash string) error
// SetChildExitCode records the exit status of a session's agent process.
SetChildExitCode(ctx context.Context, ws WorkspaceID, id SessionID, code int) error
// NextControllerGeneration advances id's controller generation by one and
// returns the new value, atomically with respect to every other caller.
// ErrNotFound when id does not exist in ws.
NextControllerGeneration(ctx context.Context, ws WorkspaceID, id SessionID) (uint64, error)
}
SessionRepository is the workspace-keyed session persistence port. Every method mirrors one semantic read or transition the existing application behavior performs, mapped from internal/controld.Store as follows:
CreateSession → Store.CreateSession GetSession → Store.GetSession SessionByIDem → Store.SessionByIdem (idempotency replay) ListSessions → Store.ListSessions Transition → Store.Transition SetSessionSetupHash → Store.SetSessionSetupHash SetChildExitCode → Store.SetChildExitCode
NextControllerGeneration has no Store predecessor: the controller lease was process memory and is now the repository's, so a restart or a second replica cannot hand out the same authority twice.
User, token, secret, and credential operations are deliberately absent: they belong to identity and vault adapters, not to the application service.
type SessionState ¶
type SessionState string
SessionState is a session's lifecycle state. The vocabulary and the Terminal/OccupiesSlot predicates are carried byte-for-byte from the internal/controld definition so the extracted application service cannot drift from today's behavior; the extraction lanes remove the internal copy after this freeze.
const ( StateQueued SessionState = "queued" StateCreating SessionState = "creating" StateRunning SessionState = "running" StateSuspendedWarm SessionState = "suspended_warm" StateSuspendedCold SessionState = "suspended_cold" StateCanceled SessionState = "canceled" StateFailed SessionState = "failed" StateDead SessionState = "dead" StateDestroyed SessionState = "destroyed" )
func (SessionState) OccupiesSlot ¶
func (s SessionState) OccupiesSlot() bool
OccupiesSlot reports whether a session in state s counts against a runner's capacity: creating, running, or suspended_warm.
func (SessionState) Terminal ¶
func (s SessionState) Terminal() bool
Terminal reports whether s is out of the schedulable lifecycle and hidden from the default list: canceled, failed, dead, or destroyed.
type Sessions ¶
type Sessions interface {
CreateSession(context.Context, Scope, CreateSession) (Session, error)
GetSession(context.Context, Scope, SessionID) (Session, error)
ListSessions(context.Context, Scope, SessionQuery) (SessionPage, error)
DeleteSession(context.Context, Scope, DeleteSession) error
SuspendSession(context.Context, Scope, SuspendSession) (Session, error)
ResumeSession(context.Context, Scope, ResumeSession) (Session, error)
SnapshotSession(context.Context, Scope, SnapshotSession) (Checkpoint, error)
}
Sessions is the session half of the caller-facing application contract. Every method receives a host-created Scope; authorization is an Authorizer call made before any state disclosure or side effect.
type SnapshotSession ¶
type SnapshotSession struct {
ID SessionID
}
SnapshotSession is the command for SnapshotSession.
type SuspendSession ¶
SuspendSession is the command for SuspendSession. Warm selects a warm suspend (container paused in place) over a cold one (container stopped, state checkpointed).
type TerminalStream ¶
type TerminalStream interface {
Receive(context.Context) (terminal.ClientMessage, error)
Send(context.Context, terminal.ServerMessage) error
Close(error) error
}
TerminalStream is the transport adapter over complete terminal protocol messages — not a socket. The application authorizes before calling the attachment broker and does not log or persist stream messages.
type TransitionOpts ¶
type TransitionOpts struct {
RunnerID *RunnerID
Error *string
// Image, when non-nil, records the image this placement resolved for the
// session (Spec.Image): the cached checkpoint on a runner that holds it,
// else the environment's own image. Set only by a placement transition.
Image *string
}
TransitionOpts carries the columns a guarded session transition may update alongside state. A nil field leaves that column unchanged.
type UnitOfWork ¶
UnitOfWork is the host's atomicity: Run executes fn so that every repository write and event record fn makes through the context it is handed commits together or not at all. A nested Run joins the enclosing unit rather than starting another. A host without transactions (an in-memory store) runs fn directly. Run returns fn's error unchanged, and ErrUnavailable when the unit itself cannot be opened or committed; no transaction, connection, or driver type crosses this port.
type UpdateEnvironment ¶
type UpdateEnvironment struct {
ID EnvironmentID
Name *string
Image *string
Setup *string
Init *string
InitTimeoutSec *int
EgressAllow *[]string
SecretRefs *[]string
Connectors *[]Connector
Requirements *Requirements
SetupTimeoutSec *int
}
UpdateEnvironment is the command for UpdateEnvironment. Pointer fields distinguish "leave this column alone" (nil) from "set it to the zero value" (a non-nil pointer): clearing a list and keeping it are different requests. ID selects the environment.
type Usage ¶
type Usage struct {
CPUTimeSeconds float64
MemoryByteSeconds int64
StorageBytes int64
NetworkBytes int64
AgentTokenCount int64
}
Usage is the provider-neutral resource/usage fact set an Event may carry: CPU time, memory byte-seconds, storage and network bytes, and agent token counts when available. It never includes a provider rate or a customer charge.
type WorkspaceDiff ¶
type WorkspaceDiff struct {
SessionID SessionID
}
WorkspaceDiff is the command for WorkspaceDiff: the session's per-repository diff, straight from the sandbox, bounded by the public workspace contract.
type WorkspaceID ¶
type WorkspaceID string
The typed identity vocabulary. Every identity in the control contract is a distinct named string type so a workspace, an actor, a session, an environment, a pool, a runner, and an event can never be assigned to one another by accident. Provider-native identifiers are never represented: a pool and a runner are opaque Rainier identities, and an adapter maps them to whatever the provider uses.