Documentation
¶
Overview ¶
Package store defines the transactional persistence contract used by kernel controllers. Infrastructure implementations must preserve these semantics.
Index ¶
- Constants
- Variables
- func CanTransitionModelCall(from, to ModelCallStatus) bool
- func CanTransitionStep(from, to StepStatus) bool
- func CanTransitionTo(from, to ToolCallStatus) bool
- func CanTransitionWorkflow(from, to WorkflowStatus) bool
- func DenialCode(err error) (string, bool)
- func IPCMailboxConsumerName(runID string) string
- func IsRetryableTransaction(err error) bool
- func QuotaExceeded(limits, consumed, additional TaskBudget) bool
- func QuotaReservationExceeded(limits, consumed, reserved, additional TaskBudget) bool
- func RetryRetryable(ctx context.Context, fn func() (int, error)) (int, error)
- func SpawnKeyHash(arguments json.RawMessage) string
- func TaskSpecBudgetReservation(spec json.RawMessage) (tokens int64, costMicroUSD money.MicroUSD)
- func TenantShard(tenantID string, count int) int
- func ValidateModelRef(ref string) error
- func ValidateStepName(name string) error
- func ValidateToolName(name string) error
- type AcknowledgeIPCMessagesInput
- type AcknowledgeIPCMessagesResult
- type AcquireAttemptInput
- type AdmissionReason
- type AgentAddress
- type AgentVersion
- type AgentVersionStore
- type AppendIPCMessageInput
- type AppendIPCMessageResult
- type ArtifactReference
- type Attempt
- type AttemptLease
- type AuditEvent
- type AuditStore
- type AuditVerification
- type BudgetStore
- type CancelAttemptInput
- type CancelAttemptResult
- type Checkpoint
- type ClaimOutboxInput
- type ClaimTasksInput
- type ClaimWorkflowsInput
- type CommitCheckpointInput
- type CompleteAttemptInput
- type CompleteAttemptResult
- type CompleteRunInput
- type ControlStore
- type ControllerKind
- type CreateAgentVersionInput
- type CreateAgentVersionResult
- type CreateModelCallInput
- type CreateModelCallResult
- type CreateRunInput
- type CreateTaskInput
- type CreateTaskResult
- type CreateToolApprovalInput
- type CreateToolApprovalResult
- type CreateToolCallInput
- type CreateToolCallResult
- type CreateWorkflowInput
- type CreateWorkflowResult
- type CreateWorkflowStepInput
- type DecideAdmissionInput
- type DecideToolApprovalInput
- type DecideWorkflowStepApprovalInput
- type DeferTaskScheduleInput
- type FinishModelCallInput
- type HeartbeatLeaseInput
- type HeartbeatStatus
- type IPCMessage
- type IPCStore
- type KernelStore
- type Lease
- type ListAuditInput
- type ListMailboxInput
- type MailboxScopeStore
- type MemoryRecord
- type MemoryStore
- type MetricsStore
- type ModelCall
- type ModelCallStatus
- type ModelDescriptor
- type ModelStore
- type ModelUsageCertainty
- type OutboxEvent
- type PackageSignature
- type PoolHealthStore
- type PutMemoryInput
- type ReceiptStore
- type RecoverExpiredAttemptInput
- type RecoveryCandidate
- type RecoveryResult
- type RegisterModelDescriptorInput
- type RegisterToolDescriptorInput
- type ReserveTaskUsageInput
- type Run
- type RunMailboxScope
- type RuntimeAssignment
- type RuntimePolicy
- type RuntimePoolOperatorStore
- type RuntimePoolState
- type RuntimeReceipt
- type RuntimeStore
- type ScheduleTaskInput
- type SearchMemoryInput
- type SetTenantQuotaInput
- type SettleTaskUsageDeltaInput
- type SettleTaskUsageInput
- type SpawnDenial
- type SpawnGuards
- type SpawnWorkflowStepInput
- type SpawnWorkflowStepResult
- type StepStatus
- type Task
- type TaskBudget
- type TaskBudgetStatus
- type TaskCancellationStore
- type TaskClaim
- type TenantQuota
- type TenantQuotaStore
- type TenantWindowUsage
- type ToolApproval
- type ToolApprovalStatus
- type ToolCall
- type ToolCallStatus
- type ToolDescriptor
- type ToolRisk
- type ToolStore
- type TransitionAttemptInput
- type TransitionWorkflowInput
- type TransitionWorkflowStepInput
- type UpdateRuntimePoolStatusInput
- type UpdateToolCallInput
- type Workflow
- type WorkflowStatus
- type WorkflowStep
- type WorkflowStore
- type WorkflowUsage
- type WriteRuntimeReceiptInput
Constants ¶
const ( // IPCPayloadLimit bounds one message's JSON payload. A message event // travels through outbox_events to NATS, whose stream caps one message at // 1 MiB (internal/platform/outbox/jetstream.go), so the payload stays well // below that and larger content must travel as an attachment reference. IPCPayloadLimit = 256 << 10 // IPCMessageEventAggregateType is the outbox aggregate type of the event // that announces a stored message. The outbox renders subjects as // "fenced.events.<aggregate_type lowercased>.<event_type lowercased>" and // requires both tokens to match ^[A-Za-z][A-Za-z0-9_]{0,127}$, so the value // is pinned here before any delivery code exists: it may not contain '.' or // '-'. IPCMessageEventAggregateType = "ipc" // IPCMessageStoredEventType is the outbox event type of the notification // that announces a stored message. Like the aggregate type it is pinned // before the delivery code exists, because the outbox renders both into one // NATS subject ("fenced.events.ipc.messagestored") and validates each token // against ^[A-Za-z][A-Za-z0-9_]{0,127}$. // // The event announces that a message reached a mailbox. It does not mean the // message was delivered to a receiver: the runtime protocol is pull-only, so // a receiver observes its mailbox when it chooses to drain it and the // platform has no way to notify it. IPCMessageStoredEventType = "MessageStored" )
const ( // MemoryContentLimit is the canonical store's per-record content cap. MemoryContentLimit = 256 << 10 // MemoryEmbeddingDimension is the v0.1 vector space dimension. MemoryEmbeddingDimension = 384 )
const AuditSchema = "fenced.audit/v1"
AuditSchema identifies the canonical audit event encoding.
Variables ¶
var ( // ErrAgentVersionConflict reports a publish attempt that reuses an // existing (tenant, name, version) identity with a different spec. ErrAgentVersionConflict = errors.New("agent version identity already published with a different spec") // ErrAgentVersionRefInvalid reports a reference that is not a canonical // name@version token pair. ErrAgentVersionRefInvalid = errors.New("agent version reference is not canonical") )
var ( // ErrBudgetExceeded reports a usage settlement that would push a task past // its reserved ceiling. The settlement is rejected and the ledger is // marked exhausted: new consumption must stop. ErrBudgetExceeded = errors.New("task budget would be exceeded") // ErrBudgetNotReserved reports a settlement or read for a task without a // budget reservation. ErrBudgetNotReserved = errors.New("task has no budget reservation") // ErrUsageReservationConflict reports a replay that changes the amount // reserved under an existing reservation key. ErrUsageReservationConflict = errors.New("usage reservation conflicts with its replay") )
var ( // ErrIPCAddressUnscoped reports an address that names only an agent // version. Mailboxes are instance-scoped: a version-only address would be // drained by whichever instance polls first, which is a competing-consumer // semantic the v1 contract does not define. ErrIPCAddressUnscoped = errors.New("ipc address must name an instance") // ErrIPCPayloadTooLarge reports a payload above IPCPayloadLimit. ErrIPCPayloadTooLarge = errors.New("ipc payload exceeds the mailbox limit") // ErrIPCDeadlineElapsed reports a deadline that does not lie after SentAt: // such a message would be born already expired, which is a caller bug // rather than a message to store. ErrIPCDeadlineElapsed = errors.New("ipc message deadline has already elapsed") )
var ( // ErrModelNotFound reports a model descriptor that is not registered in // the tenant's registry. ErrModelNotFound = errors.New("model descriptor not found") // ErrModelSpecConflict reports a registration that reuses an existing // (tenant, provider, model) identity with a different spec. ErrModelSpecConflict = errors.New("model identity already registered with a different spec") // ErrModelCallTerminal reports usage settlement or finishing on a call // that already reached a terminal state. ErrModelCallTerminal = errors.New("model call already reached a terminal state") )
var ( ErrNoAssignment = fmt.Errorf("no runtime assignment available") ErrLeaseNotExpired = fmt.Errorf("runtime lease has not expired") )
var ( ErrNotFound = errors.New("kernel object not found") ErrVersionConflict = errors.New("resource version conflict") ErrInvalidTransition = errors.New("invalid lifecycle transition") ErrIdempotencyConflict = errors.New("idempotency key reused with different request") ErrLeaseHeld = errors.New("run already has an active lease") ErrFenced = errors.New("attempt fencing token is stale") ErrCompletionPending = errors.New("completed attempt is awaiting result commit") ErrResultRequired = errors.New("durable result reference is required") // ErrRetryableTransaction marks a transient serialization failure that // callers must retry with bounded backoff (ADR-002: SERIALIZABLE with // bounded retries). ErrRetryableTransaction = errors.New("retryable transaction conflict") )
var ( // ErrToolNotFound reports a tool descriptor that is not registered in the // tenant's registry. ErrToolNotFound = errors.New("tool descriptor not found") // ErrToolSpecConflict reports a registration that reuses an existing // (tenant, name, version) identity with a different spec. ErrToolSpecConflict = errors.New("tool version identity already registered with a different spec") // ErrApprovalNotUsable reports an approval that cannot authorize an // invocation: wrong binding, expired, or not approved. ErrApprovalNotUsable = errors.New("approval cannot authorize this invocation") )
var ( // ErrWorkflowNotFound reports a workflow outside the tenant's scope. ErrWorkflowNotFound = errors.New("workflow not found") // ErrStepNotFound reports a step that does not belong to the workflow. ErrStepNotFound = errors.New("workflow step not found") )
var AuditGenesisHash = sha256.Sum256([]byte("fenced-audit-genesis-v1"))
AuditGenesisHash anchors the first event of every tenant's chain: the first event's PrevHash equals this constant, so a truncated chain (events deleted from the head) is detectable.
var ErrAuditChainBroken = errors.New("audit chain integrity check failed")
ErrAuditChainBroken reports a hash-chain integrity failure at a known seq.
var ErrCapacityExhausted = errors.New("runtime pool capacity exhausted")
var ErrMemoryNotFound = errors.New("memory record not found")
ErrMemoryNotFound reports a memory record that does not exist in the tenant's scope.
var ErrMemorySearchRequired = errors.New("memory search requires a keyword query or an embedding")
ErrMemorySearchRequired reports a search with neither a keyword query nor an embedding vector.
var ErrMemoryTooLarge = errors.New("memory content exceeds 256 KiB")
ErrMemoryTooLarge reports content that exceeds the canonical store limit.
var ErrPoolCapacityNotInitialized = errors.New("runtime pool capacity ledger is not initialized")
ErrPoolCapacityNotInitialized is returned when placement targets a pool whose durable capacity ledger row has not been registered by the runtime pool registry. Scheduling fails closed instead of bootstrapping totals from a caller snapshot.
var ErrPoolOperatorDenied = errors.New("runtime pool operator grant is required")
ErrPoolOperatorDenied reports a pool status change attempted by a principal without an operator grant. Tenant usage grants never imply operator authority on shared pools.
var ErrSpawnDenied = errors.New("spawn denied")
ErrSpawnDenied reports a dynamic-spawn guard rejection.
var ErrTenantQuotaExceeded = errors.New("tenant aggregate consumption quota would be exceeded")
ErrTenantQuotaExceeded reports an admission that would push a tenant's windowed aggregate consumption past its configured limits. The admission is rejected and nothing is recorded; the task stays queued and is rejected with a recorded TENANT_QUOTA_EXCEEDED decision on the next claim round.
var MemorySensitivities = map[string]struct{}{
"internal": {}, "confidential": {}, "restricted": {},
}
MemorySensitivities are the v0.1 sensitivity tiers; retrieval filters on them before scoring (ADR-009: the ACL check runs before retrieval).
Functions ¶
func CanTransitionModelCall ¶
func CanTransitionModelCall(from, to ModelCallStatus) bool
CanTransitionModelCall defines the model-call state machine.
func CanTransitionStep ¶
func CanTransitionStep(from, to StepStatus) bool
CanTransitionStep defines the step state machine. RUNNING → PENDING is the single-step retry path; it never touches sibling steps.
func CanTransitionTo ¶
func CanTransitionTo(from, to ToolCallStatus) bool
CanTransitionTo defines the decision-ledger state machine.
func CanTransitionWorkflow ¶
func CanTransitionWorkflow(from, to WorkflowStatus) bool
CanTransitionWorkflow defines the workflow state machine.
func DenialCode ¶
DenialCode extracts the stable denial code of a spawn error, if any.
func IPCMailboxConsumerName ¶
IPCMailboxConsumerName renders the inbox_receipts consumer name a drain of the mailbox for runID must use. Receipts are keyed by (tenant, consumer name, message id), so scoping the name to the receiving run is what makes a redelivery idempotent without letting one run's receipt hide a message from another run's drain.
func IsRetryableTransaction ¶
IsRetryableTransaction reports whether err is a transient transaction failure that may be retried with backoff.
func QuotaExceeded ¶
func QuotaExceeded(limits, consumed, additional TaskBudget) bool
QuotaExceeded reports whether additional usage would push a tenant's windowed consumption past any configured limit. A limit of 0 means the dimension is unlimited.
func QuotaReservationExceeded ¶
func QuotaReservationExceeded(limits, consumed, reserved, additional TaskBudget) bool
QuotaReservationExceeded is the v0.8 admission gate: additional usage is rejected when consumed plus the reserved ceilings of in-flight tasks plus the additional ceiling would exceed any limit. Reservation closes the concurrent-admission overshoot of the v0.6 consumed-only gate.
func RetryRetryable ¶
RetryRetryable runs fn, retrying transient transaction conflicts with bounded exponential backoff (ADR-002: SERIALIZABLE with bounded retries). Non-retryable errors and context cancellation return immediately.
func SpawnKeyHash ¶
func SpawnKeyHash(arguments json.RawMessage) string
SpawnKeyHash fingerprints the spawn arguments into the idempotent spawn_key suffix.
func TaskSpecBudgetReservation ¶
func TaskSpecBudgetReservation(spec json.RawMessage) (tokens int64, costMicroUSD money.MicroUSD)
TaskSpecBudgetReservation extracts the token and cost ceiling a merged workflow step spec will reserve at admission. It mirrors the admission controller's workload budget decode so the step reservation equals the task ledger reservation that later replaces it.
func TenantShard ¶
TenantShard returns the ADR-016 shard for a tenant: the first 32 bits of md5(tenant_id) modulo count. It mirrors the SQL expression used by ClaimTasks exactly, so tests can assert the filter deterministically. md5 is used instead of hashing functions like hashtext, which PostgreSQL does not guarantee stable across major versions.
func ValidateModelRef ¶
ValidateModelRef rejects model references that are not safe canonical provider/model tokens.
func ValidateStepName ¶
ValidateStepName rejects step names that are not canonical tokens.
func ValidateToolName ¶
ValidateToolName rejects tool names that are not safe canonical tokens.
Types ¶
type AcknowledgeIPCMessagesInput ¶
type AcknowledgeIPCMessagesInput struct {
TenantID string
ConsumerName string
MessageIDs []uuid.UUID
AcknowledgedAt time.Time
}
AcknowledgeIPCMessagesInput records that a consumer has observed a batch of messages, so a later drain does not return them again.
func (AcknowledgeIPCMessagesInput) Validate ¶
func (in AcknowledgeIPCMessagesInput) Validate() error
Validate rejects an acknowledgement that cannot be applied as asked.
type AcknowledgeIPCMessagesResult ¶
type AcknowledgeIPCMessagesResult struct {
Acknowledged []uuid.UUID
AlreadyAcknowledged []uuid.UUID
}
AcknowledgeIPCMessagesResult partitions the batch into receipts this call created and receipts an earlier call had already created. Both are applied; the split exists so a retry can be told apart from a first attempt.
type AcquireAttemptInput ¶
type AdmissionReason ¶
type AgentAddress ¶
AgentAddress names one mailbox. AgentVersionRef is an immutable reference in agentversion.FormatRef form ("[namespace/]name@version"), not a mutable agent name. Instance is the receiving run id, never an attempt id: an attempt is a replaceable execution attempt of a run, so addressing the attempt would orphan every message the moment that attempt failed.
func ParseAgentAddress ¶
func ParseAgentAddress(canonical string) (AgentAddress, error)
ParseAgentAddress splits the canonical form written by Canonical.
func (AgentAddress) Canonical ¶
func (a AgentAddress) Canonical() string
Canonical renders the stored form of the address. The round trip through ParseAgentAddress is total: Validate rejects any segment containing the separator, so the split cannot be ambiguous.
func (AgentAddress) Validate ¶
func (a AgentAddress) Validate() error
Validate reports whether the address names a single mailbox. A version-only address is rejected with ErrIPCAddressUnscoped.
type AgentVersion ¶
type AgentVersion struct {
ID uuid.UUID
TenantID string
Namespace string
Name string
Version string
Spec json.RawMessage
SpecDigest [sha256.Size]byte
ResourceVersion int64
CreatedAt time.Time
PackageSignature *PackageSignature
}
AgentVersion is an immutable published agent specification. The resource version is always 1: upgrades create new rows instead of mutating this one.
func (AgentVersion) Ref ¶
func (v AgentVersion) Ref() string
Ref returns the canonical reference used by tasks. The default namespace is elided so historical "name@version" references are unchanged; any other namespace is written as "namespace/name@version" (P1-07).
type AgentVersionStore ¶
type AgentVersionStore interface {
CreateAgentVersion(context.Context, CreateAgentVersionInput) (CreateAgentVersionResult, error)
GetAgentVersion(context.Context, string, uuid.UUID) (AgentVersion, error)
GetAgentVersionByRef(context.Context, string, string) (AgentVersion, error)
}
type AppendIPCMessageInput ¶
type AppendIPCMessageInput struct {
TenantID string
ID uuid.UUID
FromAgentVersionRef string
To AgentAddress
Kind string
// Payload is the message body as a JSON document. An empty body is
// written as {}.
Payload json.RawMessage
// Attachments is a JSON array of reference objects. It is stored without
// being interpreted; a payload above IPCPayloadLimit must travel this way.
Attachments json.RawMessage
CorrelationID string
// ReplyToMessageID is uuid.Nil when the message is not a reply.
ReplyToMessageID uuid.UUID
IdempotencyKey string
TraceID string
SentAt time.Time
// Deadline is optional; the zero time stores no deadline.
Deadline time.Time
}
AppendIPCMessageInput stores one message in the recipient's mailbox.
ID and SentAt are caller-supplied, not generated here: a send retried after a connection failure must resolve to the message the first attempt created and must report the original send time, so both fields have to survive the retry unchanged.
func (AppendIPCMessageInput) Validate ¶
func (in AppendIPCMessageInput) Validate() error
Validate rejects a message that cannot be stored as asked. Every check is a function of the input alone, never of the wall clock, so replaying the same logical send reaches the same verdict however long the retry took.
type AppendIPCMessageResult ¶
type AppendIPCMessageResult struct {
Message IPCMessage
Replayed bool
}
AppendIPCMessageResult reports the stored message. Replayed is true when the idempotency key resolved to a message an earlier attempt had already stored, in which case Message is that original message rather than a new one.
type ArtifactReference ¶
type ArtifactReference struct {
ID uuid.UUID
URI string
SHA256 [sha256.Size]byte
SizeBytes int64
MediaType string
}
func (ArtifactReference) DigestHex ¶
func (a ArtifactReference) DigestHex() string
func (ArtifactReference) Validate ¶
func (a ArtifactReference) Validate() error
type Attempt ¶
type Attempt struct {
ID uuid.UUID
TenantID string
RunID uuid.UUID
Ordinal int
Phase domain.AttemptPhase
RuntimeClass string
RuntimePoolID string
RuntimeInstanceID string
FencingToken int64
FailureCode string
FailureMessage string
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
StartedAt *time.Time
FinishedAt *time.Time
}
type AttemptLease ¶
type AuditEvent ¶
type AuditEvent struct {
ID uuid.UUID
TenantID string
Seq int64
PrevHash [sha256.Size]byte
ChainHash [sha256.Size]byte
EventType string
ResourceType string
ResourceID uuid.UUID
Actor string
Details json.RawMessage
OccurredAt time.Time
}
AuditEvent is one transactional append-only audit record.
func (AuditEvent) ComputeChainHash ¶
func (e AuditEvent) ComputeChainHash() [sha256.Size]byte
ComputeChainHash returns the canonical chain hash of the event: the value the next event's PrevHash must equal. The encoding is length-prefixed so the concatenation is unambiguous regardless of field content.
type AuditStore ¶
type AuditStore interface {
ListAudit(context.Context, ListAuditInput) ([]AuditEvent, error)
GetAuditEvent(context.Context, string, uuid.UUID) (AuditEvent, error)
VerifyAuditChain(context.Context, string) (AuditVerification, error)
ExportAuditChain(context.Context, string) ([]AuditEvent, error)
}
AuditStore is the read surface of the audit ledger.
type AuditVerification ¶
type AuditVerification struct {
Valid bool
Checked int64
FirstBrokenSeq int64 // 0 when the chain is valid
HeadSeq int64
HeadHash [sha256.Size]byte
}
AuditVerification is the result of a full chain integrity walk.
type BudgetStore ¶
type BudgetStore interface {
// GetTaskBudget returns the reservation and cumulative consumption of a
// task, or ErrBudgetNotReserved when the task carries no budget.
GetTaskBudget(context.Context, string, uuid.UUID) (TaskBudgetStatus, error)
// SettleTaskUsage appends one idempotent usage settlement. A settlement
// that would exceed the reservation is rejected with ErrBudgetExceeded and
// marks the ledger exhausted without being recorded. Replays of an
// already-recorded settlement return the current status.
SettleTaskUsage(context.Context, SettleTaskUsageInput) (TaskBudgetStatus, error)
// SettleTaskUsageDelta settles the remainder between a family's already
// settled usage and a cumulative target, exactly once per IdempotencyKey.
// The hard stop and replay semantics match SettleTaskUsage; a family that
// already settled at least the target settles nothing.
SettleTaskUsageDelta(context.Context, SettleTaskUsageDeltaInput) (TaskBudgetStatus, error)
// ReserveTaskUsage atomically protects headroom before a provider or tool
// call starts. Replays with the same key and amount are idempotent.
ReserveTaskUsage(context.Context, ReserveTaskUsageInput) error
// ReleaseTaskUsageReservation is idempotent and must run on every terminal
// call path. Expired reservations are reclaimed by reconciliation.
ReleaseTaskUsageReservation(context.Context, string, uuid.UUID, string) error
}
type CancelAttemptInput ¶
type CancelAttemptInput struct {
TenantID string
AttemptID uuid.UUID
FencingToken int64
ExpectedAttemptVersion int64
IdempotencyKey string
}
func (CancelAttemptInput) RequestHash ¶
func (in CancelAttemptInput) RequestHash() ([sha256.Size]byte, error)
type CancelAttemptResult ¶
type Checkpoint ¶
type Checkpoint struct {
ID uuid.UUID
TenantID string
RunID uuid.UUID
AttemptID uuid.UUID
Ordinal int
FencingToken int64
AgentVersionRef string
RuntimeClass string
Provider string
RuntimeABI string
SchemaVersion string
State ArtifactReference
ConfirmedReceiptIDs []string
EnvelopeSHA256 [sha256.Size]byte
CreatedAt time.Time
}
type ClaimOutboxInput ¶
type ClaimTasksInput ¶
type ClaimTasksInput struct {
Kind ControllerKind
Phase domain.TaskPhase
OwnerID string
Limit int
TTL time.Duration
// ShardIndex / ShardCount are the tenant-consistent shard filter
// (ADR-016): when ShardCount > 0, only tasks whose tenant maps to
// ShardIndex are claimable. Zero values mean no sharding (every instance
// claims every tenant). All instances must share the same shard count.
ShardIndex int
ShardCount int
}
type ClaimWorkflowsInput ¶
ClaimWorkflowsInput bounds one orchestrator claim round.
type CommitCheckpointInput ¶
type CommitCheckpointInput struct {
TenantID string
AttemptID uuid.UUID
FencingToken int64
ExpectedAttemptVersion int64
IdempotencyKey string
CheckpointID uuid.UUID
AgentVersionRef string
Provider string
RuntimeABI string
SchemaVersion string
State ArtifactReference
ConfirmedReceiptIDs []string
}
func (CommitCheckpointInput) Normalize ¶
func (in CommitCheckpointInput) Normalize() (CommitCheckpointInput, [sha256.Size]byte, error)
type CompleteAttemptInput ¶
type CompleteAttemptInput struct {
TenantID string
AttemptID uuid.UUID
FencingToken int64
ExpectedAttemptVersion int64
IdempotencyKey string
Result ArtifactReference
}
func (CompleteAttemptInput) RequestHash ¶
func (in CompleteAttemptInput) RequestHash() ([sha256.Size]byte, error)
type CompleteAttemptResult ¶
type CompleteRunInput ¶
type ControlStore ¶
type ControlStore interface {
GetTask(context.Context, string, uuid.UUID) (Task, error)
ClaimTasks(context.Context, ClaimTasksInput) ([]TaskClaim, error)
ReleaseTaskClaim(context.Context, TaskClaim) error
DecideAdmission(context.Context, DecideAdmissionInput) (Task, error)
ScheduleTask(context.Context, ScheduleTaskInput) (AttemptLease, error)
DeferTaskSchedule(context.Context, DeferTaskScheduleInput) (Task, error)
ClaimOutbox(context.Context, ClaimOutboxInput) ([]OutboxEvent, error)
MarkOutboxPublished(context.Context, uuid.UUID, string, int64, time.Time) error
MarkOutboxFailed(context.Context, uuid.UUID, string, int64, string, time.Time) error
GetAgentVersionByRef(context.Context, string, string) (AgentVersion, error)
}
type ControllerKind ¶
type ControllerKind string
const ( ControllerAdmission ControllerKind = "ADMISSION" ControllerScheduling ControllerKind = "SCHEDULING" )
type CreateAgentVersionInput ¶
type CreateAgentVersionInput struct {
ID uuid.UUID
TenantID string
Namespace string
Name string
Version string
Spec json.RawMessage
PackageSignature *PackageSignature
}
func (CreateAgentVersionInput) ValidateAndHash ¶
func (in CreateAgentVersionInput) ValidateAndHash() (json.RawMessage, [sha256.Size]byte, error)
ValidateAndHash bounds the publication and derives the canonical spec document and its immutable digest.
type CreateAgentVersionResult ¶
type CreateAgentVersionResult struct {
AgentVersion AgentVersion
Existing bool
}
type CreateModelCallInput ¶
type CreateModelCallInput struct {
ID uuid.UUID
TenantID string
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
ModelRef string
// PriceRevision pins the price table the call is metered against.
PriceRevision string
IdempotencyKey string
}
func (CreateModelCallInput) RequestHash ¶
func (in CreateModelCallInput) RequestHash() ([sha256.Size]byte, error)
type CreateModelCallResult ¶
type CreateRunInput ¶
type CreateTaskInput ¶
type CreateTaskInput struct {
ID uuid.UUID
TenantID string
Namespace string
AgentVersionRef string
Goal string
Spec json.RawMessage
IdempotencyKey string
WorkflowID *uuid.UUID
WorkflowStepID *uuid.UUID
WorkflowStepName string
WorkflowAttempt int
ParentTaskID *uuid.UUID
}
func (CreateTaskInput) ValidateAndHash ¶
func (in CreateTaskInput) ValidateAndHash() (json.RawMessage, [32]byte, error)
type CreateTaskResult ¶
type CreateToolApprovalInput ¶
type CreateToolApprovalResult ¶
type CreateToolApprovalResult struct {
ToolApproval ToolApproval
Existing bool
}
type CreateToolCallInput ¶
type CreateToolCallInput struct {
ID uuid.UUID
TenantID string
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
ToolName string
ToolVersion string
Action string
Resource string
ArgsHash [sha256.Size]byte
IdempotencyKey string
}
func (CreateToolCallInput) RequestHash ¶
func (in CreateToolCallInput) RequestHash() ([sha256.Size]byte, error)
RequestHash is the canonical digest of the invocation intent, used to detect idempotency-key reuse with different semantics.
type CreateToolCallResult ¶
type CreateWorkflowInput ¶
type CreateWorkflowInput struct {
ID uuid.UUID
TenantID string
Namespace string
IdempotencyKey string
Goal string
Spec json.RawMessage
Steps []CreateWorkflowStepInput
// Budget ceilings decoded from the workflow document; zero leaves
// the dimension unbounded.
BudgetMaxTasks int64
BudgetMaxTokens int64
BudgetMaxCostMicroUSD money.MicroUSD
DeadlineAt *time.Time
}
CreateWorkflowInput creates a workflow and its steps atomically.
func (CreateWorkflowInput) RequestHash ¶
func (in CreateWorkflowInput) RequestHash() ([sha256.Size]byte, error)
RequestHash fingerprints the tenant-scoped workflow definition so an idempotency-key replay of a different definition is rejected.
type CreateWorkflowResult ¶
CreateWorkflowResult reports the created workflow and whether an idempotency-key replay returned the existing definition.
type CreateWorkflowStepInput ¶
type CreateWorkflowStepInput struct {
Name string
Spec json.RawMessage // per-step workload spec overlay
AgentVersionRef string
Goal string
DependsOn []string
ConditionStep string
ConditionContains string
ConditionEquals string
RequiresApproval bool
MaxAttempts int
}
CreateWorkflowStepInput is one declared step of a new workflow.
type DecideAdmissionInput ¶
type DecideAdmissionInput struct {
TaskID uuid.UUID
TenantID string
OwnerID string
ClaimFencingToken int64
ExpectedTaskVersion int64
Admit bool
ReasonCode string
Reasons []AdmissionReason
EvaluatorVersion string
// AgentVersionID binds the task to the immutable published version its
// reference resolved to. It is set by the admission controller whenever
// the reference is resolvable, regardless of the admission outcome.
AgentVersionID *uuid.UUID
// Budget is the task's reserved ceiling, derived from its workload spec
// by the admission controller. When set and the task is admitted, the
// ledger row is created in the same transaction as the admission
// decision; nil means the task carries no budget.
Budget *TaskBudget
// PolicyRevision records the Rego policy revision that produced the
// decision; empty when no policy engine participated.
PolicyRevision string
}
type DecideToolApprovalInput ¶
type DecideToolApprovalInput struct {
TenantID string
ApprovalID uuid.UUID
ExpectedVersion int64
Decision ToolApprovalStatus
DecidedBy string
Now time.Time
}
func (DecideToolApprovalInput) Valid ¶
func (in DecideToolApprovalInput) Valid() bool
Valid checks the decision request: only APPROVED/REJECTED decisions, an identified decider, and a current clock.
type DecideWorkflowStepApprovalInput ¶
type DecideWorkflowStepApprovalInput struct {
TenantID string
WorkflowID uuid.UUID
StepName string
ExpectedVersion int64
Approved bool
DecidedBy string
}
DecideWorkflowStepApprovalInput records a human decision on one step.
type DeferTaskScheduleInput ¶
type DeferTaskScheduleInput struct {
TaskID uuid.UUID
TenantID string
OwnerID string
ClaimFencingToken int64
ExpectedTaskVersion int64
Until time.Time
Rejection json.RawMessage
}
DeferTaskScheduleInput releases the scheduler's claim on a task that no pool could place and defers its next scheduling attempt until Until (O6). The deferral is recorded on the task — not on the claim — so every controller instance agrees on the backoff, and the claim is deleted in the same transaction (immediate release, no waiting out the claim TTL).
type FinishModelCallInput ¶
type FinishModelCallInput struct {
TenantID string
ModelCallID uuid.UUID
ExpectedVersion int64
Status ModelCallStatus
InputTokens int64
OutputTokens int64
CostMicroUSD money.MicroUSD
PriceRevision string
ProviderRequestID string
FinishReason string
UsageCertainty ModelUsageCertainty
}
FinishModelCallInput finalizes one model invocation with the final usage.
type HeartbeatLeaseInput ¶
type HeartbeatStatus ¶
HeartbeatStatus is the narrow state a lease renewal needs: whether the task has a pending cancellation and the attempt's current resource version. It lets the Runtime Protocol heartbeat answer cancel checks without re-materializing the full assignment.
type IPCMessage ¶
type IPCMessage struct {
Sequence int64
ID uuid.UUID
TenantID string
FromAgentVersionRef string
To AgentAddress
Kind string
Payload json.RawMessage
Attachments json.RawMessage
CorrelationID string
// ReplyToMessageID is uuid.Nil when the message is not a reply.
ReplyToMessageID uuid.UUID
TraceID string
SentAt time.Time
// Deadline is the zero time when the message carries no deadline.
Deadline time.Time
}
IPCMessage is one durable message in a mailbox. Sequence is the mailbox cursor: it increases inside one mailbox but not by one, because the sequence is global to the table.
type IPCStore ¶
type IPCStore interface {
// AppendIPCMessage stores one message in the recipient's mailbox. A
// replay of the same idempotency key returns the message the first attempt
// stored, with Replayed=true; the same key carrying a different message is
// ErrIdempotencyConflict.
//
// A message that is stored for the first time also enqueues one
// IPCMessageStoredEventType event into outbox_events in the same
// transaction. A replay enqueues nothing: the message it resolves to was
// already announced, and announcing it again would turn one send into two
// events.
AppendIPCMessage(context.Context, AppendIPCMessageInput) (AppendIPCMessageResult, error)
// GetIPCMessage returns one message or ErrNotFound. A message belonging to
// another tenant is not found.
GetIPCMessage(context.Context, string, uuid.UUID) (IPCMessage, error)
// ListMailbox returns the messages addressed to To with a sequence above
// the cursor that the consumer has not receipted, in mailbox order.
ListMailbox(context.Context, ListMailboxInput) ([]IPCMessage, error)
// AcknowledgeIPCMessages records the consumer's receipts for a batch. Only
// messages that exist in the tenant may be acknowledged: a receipt for an
// unknown id would hide the real message if it arrived later.
AcknowledgeIPCMessages(context.Context, AcknowledgeIPCMessagesInput) (AcknowledgeIPCMessagesResult, error)
}
IPCStore is the durable mailbox surface. Delivery is expressed as a side effect of the durable write rather than as a method of its own: AppendIPCMessage enqueues the dispatch event in the same transaction, so a stored message and its announcement cannot diverge. Publishing that event to NATS is the dispatcher's job (internal/platform/outbox), and notifying a receiver is deliberately absent: fenced.runtime.v1 is pull-only, so a receiver drains its mailbox on its own schedule and no method here pretends otherwise.
type KernelStore ¶
type KernelStore interface {
CreateTask(context.Context, CreateTaskInput) (CreateTaskResult, error)
TransitionTask(context.Context, string, uuid.UUID, int64, domain.TaskPhase) (Task, error)
CreateRun(context.Context, CreateRunInput) (Run, error)
AcquireAttempt(context.Context, AcquireAttemptInput) (AttemptLease, error)
TransitionAttempt(context.Context, TransitionAttemptInput) (Attempt, error)
HeartbeatLease(context.Context, HeartbeatLeaseInput) (Lease, error)
CompleteRun(context.Context, CompleteRunInput) (Run, Task, error)
}
type ListAuditInput ¶
type ListAuditInput struct {
TenantID string
// AfterSeq returns events with seq > AfterSeq (cursor semantics).
AfterSeq int64
Limit int
}
ListAuditInput pages a tenant's ledger forward by seq.
type ListMailboxInput ¶
type ListMailboxInput struct {
TenantID string
To AgentAddress
// AfterSequence is exclusive cursor semantics, matching
// ListAuditInput.AfterSeq.
AfterSequence int64
Limit int
// ConsumerName scopes the receipt. Messages already receipted for this
// consumer are not returned. Use IPCMailboxConsumerName to derive it from
// the receiving run id.
ConsumerName string
}
ListMailboxInput drains one mailbox forward by sequence.
func (ListMailboxInput) Validate ¶
func (in ListMailboxInput) Validate() error
Validate rejects a drain that could read another mailbox or an unbounded page.
type MailboxScopeStore ¶
type MailboxScopeStore interface {
// GetRunMailboxScope returns the scope of runID within the tenant, or
// ErrNotFound when no such run exists in that tenant.
GetRunMailboxScope(context.Context, string, uuid.UUID) (RunMailboxScope, error)
}
MailboxScopeStore resolves the run an address names. It is separate from IPCStore because it reads the run/task tables rather than the mailbox, and because a send needs it before it has anything to store: without the check, a sender that mistypes a run id stores a message into a mailbox that is never drained, and nothing reports it.
type MemoryRecord ¶
type MemoryRecord struct {
ID uuid.UUID
TenantID string
Namespace string
Key string
ContentType string
Content string
Embedding []float32
EmbeddingProvider string
Sensitivity string
SourceTaskID *uuid.UUID
SourceRunID *uuid.UUID
SourceAttemptID *uuid.UUID
Provenance json.RawMessage
RetentionUntil *time.Time
TombstoneAt *time.Time
SupersededBy *uuid.UUID
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
MemoryRecord is one canonical memory entry: identity, provenance, ACL, tenant, sensitivity, version, retention and tombstone state. Content lives in PostgreSQL for v0.1 (FTS + pgvector share the transaction system); large payloads move to the object store behind the same interface later.
func (MemoryRecord) ContentHash ¶
func (r MemoryRecord) ContentHash() ([sha256.Size]byte, error)
ContentHash returns the SHA-256 of the canonical memory document; a PutMemory with the same (tenant, namespace, key) and an identical document replays idempotently instead of creating a new version. Nil provenance is canonicalized to {} and retention times to UTC so stored and submitted documents hash identically.
type MemoryStore ¶
type MemoryStore interface {
// PutMemory inserts or updates the record with the given stable
// (tenant, namespace, key). An identical document replays idempotently
// (Existing=true, no version bump); a different document is a new
// version (correction) and resurrects a tombstoned record.
PutMemory(context.Context, PutMemoryInput) (MemoryRecord, bool, error)
// GetMemory returns the record (including tombstone state) or
// ErrMemoryNotFound.
GetMemory(context.Context, string, uuid.UUID) (MemoryRecord, error)
// SearchMemory returns live (non-tombstoned, unexpired) records scored
// by keyword FTS/trigram similarity and optional vector cosine distance,
// tenant- and sensitivity-filtered before scoring.
SearchMemory(context.Context, SearchMemoryInput) ([]MemoryRecord, error)
// TombstoneMemory soft-deletes a record (ADR-009 deletion intent), CAS on
// resource version.
TombstoneMemory(context.Context, string, uuid.UUID, int64) (MemoryRecord, error)
}
type MetricsStore ¶
type MetricsStore interface {
AggregateMetrics(context.Context, string, time.Time) (*observability.Metrics, error)
}
MetricsStore exposes the aggregated platform observability surface (§Phase-7 core metrics), consistent with the data the store's AggregateMetrics method produces.
type ModelCall ¶
type ModelCall struct {
ID uuid.UUID
TenantID string
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
ModelRef string
Status ModelCallStatus
IdempotencyKey string
RequestHash [sha256.Size]byte
InputTokens int64
OutputTokens int64
CostMicroUSD money.MicroUSD
PriceRevision string
ProviderRequestID string
FinishReason string
UsageCertainty ModelUsageCertainty
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
ModelCall is the durable ledger row of one model invocation. Usage and cost are accumulated at settlement; content is never stored (prompt/completion stay out of kernel telemetry by policy).
type ModelCallStatus ¶
type ModelCallStatus string
ModelCallStatus is the lifecycle of one model invocation.
const ( ModelCallStarted ModelCallStatus = "STARTED" ModelCallCompleted ModelCallStatus = "COMPLETED" ModelCallFailed ModelCallStatus = "FAILED" ModelCallStopped ModelCallStatus = "STOPPED" )
func (ModelCallStatus) Terminal ¶
func (s ModelCallStatus) Terminal() bool
type ModelDescriptor ¶
type ModelDescriptor struct {
ID uuid.UUID
TenantID string
Provider string
ModelName string
SupportsStreaming bool
InputPriceMicroUSDPerMillion money.MicroUSD
OutputPriceMicroUSDPerMillion money.MicroUSD
PriceRevision string
SpecHash [sha256.Size]byte
CreatedAt time.Time
}
ModelDescriptor is a versioned declaration of a model capability and its price table. It is immutable per (tenant, provider, model): a price change registers a new price revision under the same identity.
func (ModelDescriptor) Ref ¶
func (d ModelDescriptor) Ref() string
Ref returns the canonical provider/model reference.
func (ModelDescriptor) Validate ¶
func (d ModelDescriptor) Validate() error
type ModelStore ¶
type ModelStore interface {
RegisterModelDescriptor(context.Context, RegisterModelDescriptorInput) (ModelDescriptor, error)
GetModelDescriptor(context.Context, string, string, string) (ModelDescriptor, error)
CreateModelCall(context.Context, CreateModelCallInput) (CreateModelCallResult, error)
GetModelCall(context.Context, string, uuid.UUID) (ModelCall, error)
FinishModelCall(context.Context, FinishModelCallInput) (ModelCall, error)
}
type ModelUsageCertainty ¶
type ModelUsageCertainty string
const ( ModelUsageKnownZero ModelUsageCertainty = "KNOWN_ZERO_USAGE" ModelUsageKnown ModelUsageCertainty = "KNOWN_USAGE" ModelUsageUnknown ModelUsageCertainty = "UNKNOWN_USAGE" )
func (ModelUsageCertainty) Valid ¶
func (c ModelUsageCertainty) Valid() bool
type OutboxEvent ¶
type PackageSignature ¶
type PackageSignature struct {
KeyID string // signing key identity in the trust registry
Signature string // base64 raw std ed25519 signature over the manifest digest
ManifestDigest string // hex sha256 of the canonical signed manifest
}
PackageSignature is the verified signature envelope persisted with a publication (ADR-010). It is populated only when publish admission verified the signed Agent Package; all three fields are set together or none.
type PoolHealthStore ¶
type PoolHealthStore interface {
// PoolInstanceHealth reports whether each runtime instance is presumed
// alive at now. An instance is unhealthy while it holds an unreleased
// lease whose heartbeat is stale: the lease expired (expires_at <= now)
// or was not renewed within the freshness window (heartbeat_at <= now -
// freshness). An instance with no unreleased leases is healthy — idling
// is not a failure signal. Every requested instance ID appears in the
// result; callers treat an ID missing from the map as unhealthy
// (fail-closed).
PoolInstanceHealth(context.Context, []string, time.Time, time.Duration) (map[string]bool, error)
}
PoolHealthStore reports runtime instance liveness derived from lease heartbeats (v0.6): placement consults it before scheduling so that pools whose worker stopped renewing its lease are rejected instead of stranding a new attempt until lease-expiry recovery.
type PutMemoryInput ¶
type PutMemoryInput struct {
TenantID string
Namespace string
Key string
ContentType string
Content string
Embedding []float32
EmbeddingProvider string
Sensitivity string
SourceTaskID *uuid.UUID
SourceRunID *uuid.UUID
SourceAttemptID *uuid.UUID
Provenance json.RawMessage
RetentionUntil *time.Time
}
func (PutMemoryInput) Validate ¶
func (in PutMemoryInput) Validate() error
type ReceiptStore ¶
type RecoverExpiredAttemptInput ¶
type RecoverExpiredAttemptInput struct {
TenantID string
AttemptID uuid.UUID
FencingToken int64
NewAttemptID uuid.UUID
NewLeaseID uuid.UUID
LeaseTTL time.Duration
MaxAttempts int
// DeadlineExceeded terminally stops the task even if the worker lease is
// still healthy. It must never create a retry attempt.
DeadlineExceeded bool
}
type RecoveryCandidate ¶
type RecoveryResult ¶
type RecoveryResult struct {
Retried bool
Lease AttemptLease
}
type RegisterModelDescriptorInput ¶
type RegisterModelDescriptorInput struct {
TenantID string
Provider string
ModelName string
SupportsStreaming bool
InputPriceMicroUSDPerMillion money.MicroUSD
OutputPriceMicroUSDPerMillion money.MicroUSD
PriceRevision string
}
func (RegisterModelDescriptorInput) ValidateAndHash ¶
func (in RegisterModelDescriptorInput) ValidateAndHash() (ModelDescriptor, [sha256.Size]byte, error)
type RegisterToolDescriptorInput ¶
type RegisterToolDescriptorInput struct {
TenantID string
Name string
Version string
SideEffectRisk ToolRisk
Actions []string
ResourcePatterns []string
ParamsSchema json.RawMessage
}
func (RegisterToolDescriptorInput) ValidateAndHash ¶
func (in RegisterToolDescriptorInput) ValidateAndHash() (ToolDescriptor, [sha256.Size]byte, error)
ValidateAndHash returns the normalized descriptor document and its digest.
type ReserveTaskUsageInput ¶
type ReserveTaskUsageInput struct {
TenantID string
TaskID uuid.UUID
ReservationKey string
Amount TaskBudget
ExpiresAt time.Time
}
func (ReserveTaskUsageInput) Valid ¶
func (in ReserveTaskUsageInput) Valid() bool
type RunMailboxScope ¶
type RunMailboxScope struct {
TenantID string
RunID string
TaskID string
// AgentVersionRef is the version reference of the run's task. A send that
// pairs a run with any other version reference names a mailbox that no
// attempt will ever drain.
AgentVersionRef string
}
RunMailboxScope is the mailbox identity a run id resolves to. A mailbox is addressed by (agent version reference, run id), and the version reference is not a property of the run itself: it comes from the run's task, which is the immutable publication resolved during admission.
type RuntimeAssignment ¶
type RuntimeAssignment struct {
Task Task
// AgentVersion is the immutable publication resolved during admission.
// Runtime providers receive this declaration so adapter selection and
// capability grants never come from mutable Task input.
AgentVersion *AgentVersion
Run Run
Attempt Attempt
Lease Lease
ResumeCheckpoint *Checkpoint
// PendingApprovalID is the approval a WAITING_APPROVAL attempt must
// re-present to the Tool Gateway to resume execution.
PendingApprovalID *uuid.UUID
}
type RuntimePolicy ¶
type RuntimePolicy struct {
SpawnGuards SpawnGuards
}
RuntimePolicy is the dynamic-orchestration policy the controller resolves from the workflow document at runtime.
func DecodeWorkflowRuntimePolicy ¶
func DecodeWorkflowRuntimePolicy(spec json.RawMessage) RuntimePolicy
DecodeWorkflowRuntimePolicy extracts the runtime policy from a stored workflow document. Unknown documents yield the zero policy (dynamic spawn disabled).
type RuntimePoolOperatorStore ¶
type RuntimePoolOperatorStore interface {
UpdateRuntimePoolStatus(context.Context, UpdateRuntimePoolStatusInput) (RuntimePoolState, error)
}
type RuntimePoolState ¶
type RuntimeReceipt ¶
type RuntimeReceipt struct {
RequestHash [sha256.Size]byte
Response json.RawMessage
ProcessedAt time.Time
}
RuntimeReceipt is the durable outcome record of one runtime operation.
type RuntimeStore ¶
type RuntimeStore interface {
KernelStore
// WorkflowLineage resolves the workflow origin from the task's explicit
// lineage columns; ok=false marks standalone tasks. The version is the
// workflow's current resource version at read time.
WorkflowLineage(context.Context, string, uuid.UUID) (workflowID uuid.UUID, stepName string, version int64, ok bool, err error)
PollRuntimeAssignment(context.Context, string, string) (RuntimeAssignment, error)
GetRuntimeAssignment(context.Context, string, uuid.UUID, int64) (RuntimeAssignment, error)
GetHeartbeatStatus(context.Context, string, uuid.UUID, int64) (HeartbeatStatus, error)
CommitCheckpoint(context.Context, CommitCheckpointInput) (Checkpoint, Attempt, error)
CompleteAttempt(context.Context, CompleteAttemptInput) (CompleteAttemptResult, error)
AcknowledgeCancellation(context.Context, CancelAttemptInput) (CancelAttemptResult, error)
ListExpiredAttempts(context.Context, time.Time, int) ([]RecoveryCandidate, error)
RecoverExpiredAttempt(context.Context, RecoverExpiredAttemptInput) (RecoveryResult, error)
}
type ScheduleTaskInput ¶
type ScheduleTaskInput struct {
TaskID uuid.UUID
TenantID string
OwnerID string
ClaimFencingToken int64
ExpectedTaskVersion int64
RunID uuid.UUID
AttemptID uuid.UUID
LeaseID uuid.UUID
RuntimePoolID string
RuntimeClass string
RuntimeInstanceID string
LeaseTTL time.Duration
RequestedCPU int64
RequestedMemory int64
RequestedLLMSlots int
}
type SearchMemoryInput ¶
type SearchMemoryInput struct {
TenantID string
Query string
Embedding []float32
Namespace string
Sensitivity string
Limit int
}
func (SearchMemoryInput) Validate ¶
func (in SearchMemoryInput) Validate() error
type SetTenantQuotaInput ¶
type SetTenantQuotaInput struct {
TenantID string
WindowSeconds int64
Limits TaskBudget
}
SetTenantQuotaInput configures a tenant's aggregate consumption quota. WindowSeconds must be at least 60; limits must be non-negative.
func (SetTenantQuotaInput) Valid ¶
func (in SetTenantQuotaInput) Valid() bool
type SettleTaskUsageDeltaInput ¶
type SettleTaskUsageDeltaInput struct {
TenantID string
TaskID uuid.UUID
// FamilyPrefix scopes the already-settled sum (e.g. "model:<callID>").
// Wildcards are rejected so the prefix can never widen the match.
FamilyPrefix string
// Target is the cumulative usage the family must reach.
Target TaskBudget
// IdempotencyKey is the key of the delta settlement row.
IdempotencyKey string
ReservationKey string
}
SettleTaskUsageDeltaInput settles a usage family up to a cumulative target: the delta between what the family already settled and the target is recorded under one idempotency key. The family is the set of settlements whose idempotency key is FamilyPrefix followed by ":<suffix>". This is the exact accounting primitive for model calls: per-step Settle records accrue under "model:<callID>:<seq>" and Finish settles only the remainder to reach the final cumulative total, so a stream that both settles steps and finalizes is charged exactly once.
func (SettleTaskUsageDeltaInput) Valid ¶
func (in SettleTaskUsageDeltaInput) Valid() bool
type SettleTaskUsageInput ¶
type SettleTaskUsageInput struct {
TenantID string
TaskID uuid.UUID
IdempotencyKey string
Usage TaskBudget
// ReservationKey identifies the active pre-consumption reservation that
// this settlement replaces. It is excluded from concurrent headroom.
ReservationKey string
}
func (SettleTaskUsageInput) Valid ¶
func (in SettleTaskUsageInput) Valid() bool
type SpawnDenial ¶
SpawnDenial is a structured guard rejection: the brokered tool surfaces the stable code to the agent instead of a raw error string.
func (SpawnDenial) Error ¶
func (d SpawnDenial) Error() string
func (SpawnDenial) Unwrap ¶
func (d SpawnDenial) Unwrap() error
type SpawnGuards ¶
type SpawnGuards struct {
Enabled bool
MaxDynamicSteps int64
MaxChildrenPerStep int64
MaxSpawnDepth int
MaxWorkflowSteps int64
MaxSpawnTasks int64
MaxSpawnTokens int64
MaxSpawnCostMicroUSD money.MicroUSD
}
SpawnGuards carries the dynamic-orchestration runtime limits the spawning path enforces. Zero disables a guard.
type SpawnWorkflowStepInput ¶
type SpawnWorkflowStepInput struct {
WorkflowID uuid.UUID
TenantID string
WorkflowVersion int64
ParentStepName string
Name string
Goal string
AgentVersionRef string
Spec json.RawMessage
MaxAttempts int
Guards SpawnGuards
IdempotencyKey string
Arguments json.RawMessage
}
SpawnWorkflowStepInput creates one dynamic step. SpawnKey is the brokered tool call's idempotency fingerprint: replaying the same spawn returns the existing step instead of creating a second one. The guards are the runtime policy resolved from the workflow document.
type SpawnWorkflowStepResult ¶
type SpawnWorkflowStepResult struct {
Step WorkflowStep
Workflow Workflow
WorkflowExhausted bool
Created bool
Usage WorkflowUsage
}
SpawnWorkflowStepResult reports the step (new or replayed), the workflow's budget ceilings, and the usage snapshot the guard evaluated against.
type StepStatus ¶
type StepStatus string
StepStatus is the lifecycle of one workflow step.
const ( StepPending StepStatus = "PENDING" StepWaitingApproval StepStatus = "WAITING_APPROVAL" StepRunning StepStatus = "RUNNING" StepSucceeded StepStatus = "SUCCEEDED" StepFailed StepStatus = "FAILED" StepSkipped StepStatus = "SKIPPED" StepCancelled StepStatus = "CANCELLED" )
func (StepStatus) Terminal ¶
func (s StepStatus) Terminal() bool
type Task ¶
type Task struct {
ID uuid.UUID
TenantID string
Namespace string
AgentVersionRef string
AgentVersionID *uuid.UUID
Goal string
Spec json.RawMessage
RequestHash [32]byte
IdempotencyKey string
Phase domain.TaskPhase
AdmissionReasonCode string
AdmittedAt *time.Time
CancelRequestedAt *time.Time
ActiveRunID *uuid.UUID
ResultRef string
WorkflowID *uuid.UUID
WorkflowStepID *uuid.UUID
WorkflowStepName string
WorkflowAttempt int
ParentTaskID *uuid.UUID
// ExecutionDeadlineAt is the hard stop computed when execution begins:
// min(workload deadline, start + wallSeconds).
ExecutionDeadlineAt *time.Time
// NextScheduleAttemptAt gates scheduling-claim eligibility (O6): a task
// deferred after a no-placement is not claimable by the scheduler until
// this deadline. Nil means eligible immediately.
NextScheduleAttemptAt *time.Time
// ScheduleRetryCount is the number of consecutive no-placement
// deferrals; it drives the exponential scheduling backoff and resets on
// successful placement.
ScheduleRetryCount int64
LastScheduleRejection json.RawMessage
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
type TaskBudget ¶
type TaskBudget struct {
Tokens int64
CostMicroUSD money.MicroUSD
ToolCalls int64
WallSeconds int64
}
TaskBudget is the reserved or consumed four-dimensional budget of a task. All fields are non-negative; a zero budget means the dimension is unlimited.
func (TaskBudget) Valid ¶
func (b TaskBudget) Valid() bool
func (TaskBudget) Zero ¶
func (b TaskBudget) Zero() bool
type TaskBudgetStatus ¶
type TaskBudgetStatus struct {
TaskID uuid.UUID
TenantID string
Reserved TaskBudget
Consumed TaskBudget
Exhausted bool
ResourceVersion int64
UpdatedAt time.Time
}
TaskBudgetStatus is the current reservation and cumulative consumption of a task, as derived from the append-only settlement ledger.
type TaskCancellationStore ¶
type TenantQuota ¶
type TenantQuota struct {
TenantID string
WindowSeconds int64
Limits TaskBudget
ResourceVersion int64
UpdatedAt time.Time
}
TenantQuota is a tenant's windowed aggregate consumption limits. A zero dimension means that dimension is unlimited, matching task budget semantics; a tenant without a quota row is never gated.
type TenantQuotaStore ¶
type TenantQuotaStore interface {
// SetTenantQuota configures or replaces the tenant's quota. Existing
// window consumption is preserved; only the limits and window length
// change.
SetTenantQuota(context.Context, SetTenantQuotaInput) (TenantQuota, error)
// GetTenantQuota returns the tenant's configured quota or ErrNotFound.
GetTenantQuota(context.Context, string) (TenantQuota, error)
// DeleteTenantQuota removes the tenant's quota configuration. Window
// consumption rows become inert; future admissions are unlimited until a
// new quota is configured.
DeleteTenantQuota(context.Context, string) error
// GetTenantQuotaUsage returns the consumption of the window containing at.
GetTenantQuotaUsage(context.Context, string, time.Time) (TenantWindowUsage, error)
}
TenantQuotaStore is the persistence contract for tenant aggregate consumption quotas. GetTenantQuota reports ErrNotFound for a tenant without a configured quota; GetTenantQuotaUsage reports the current window's consumption (zero usage when the tenant settled nothing in it yet) or ErrNotFound when no quota is configured.
type TenantWindowUsage ¶
type TenantWindowUsage struct {
TenantID string
WindowStart time.Time
Consumed TaskBudget
Reserved TaskBudget
ResourceVersion int64
UpdatedAt time.Time
}
TenantWindowUsage is the settled and reserved aggregate consumption of one tenant in one fixed window (v0.8: reservation holds the ceilings of admitted-but-not-terminal tasks).
type ToolApproval ¶
type ToolApproval struct {
ID uuid.UUID
TenantID string
CallID uuid.UUID
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
ToolName string
ToolVersion string
Action string
Resource string
ArgsHash [sha256.Size]byte
Status ToolApprovalStatus
RequestedAt time.Time
ExpiresAt time.Time
DecidedAt *time.Time
DecidedBy string
ResourceVersion int64
}
ToolApproval is a human authorization bound to a canonical call summary.
type ToolApprovalStatus ¶
type ToolApprovalStatus string
ToolApprovalStatus is the lifecycle of one approval request.
const ( ToolApprovalPending ToolApprovalStatus = "PENDING" ToolApprovalApproved ToolApprovalStatus = "APPROVED" ToolApprovalRejected ToolApprovalStatus = "REJECTED" ToolApprovalExpired ToolApprovalStatus = "EXPIRED" )
type ToolCall ¶
type ToolCall struct {
ID uuid.UUID
TenantID string
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
ToolName string
ToolVersion string
Action string
Resource string
ArgsHash [sha256.Size]byte
Status ToolCallStatus
DecisionReasons []string
PolicyRevision string
ApprovalID *uuid.UUID
IdempotencyKey string
RequestHash [sha256.Size]byte
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
ToolCall is the durable decision record of one invocation, bound to taskId + runId + attemptId + idempotencyKey (invariant 6).
type ToolCallStatus ¶
type ToolCallStatus string
ToolCallStatus is the decision ledger status of one invocation.
const ( ToolCallPending ToolCallStatus = "PENDING" ToolCallRequiresApproval ToolCallStatus = "REQUIRES_APPROVAL" ToolCallApproved ToolCallStatus = "APPROVED" ToolCallExecuted ToolCallStatus = "EXECUTED" ToolCallDenied ToolCallStatus = "DENIED" ToolCallFailed ToolCallStatus = "FAILED" )
type ToolDescriptor ¶
type ToolDescriptor struct {
ID uuid.UUID
TenantID string
Name string
Version string
SideEffectRisk ToolRisk
Actions []string
ResourcePatterns []string
ParamsSchema json.RawMessage
SpecHash [sha256.Size]byte
CreatedAt time.Time
}
ToolDescriptor is a versioned declaration of an external capability. A descriptor is immutable per (tenant, name, version): a change is a new version.
func (ToolDescriptor) Validate ¶
func (d ToolDescriptor) Validate() error
Validate checks the structural bounds of a descriptor. ParamsSchema must be valid JSON and bounded; semantic schema validation happens at invocation time in the tool domain.
type ToolRisk ¶
type ToolRisk string
ToolRisk classifies the side-effect surface of a tool. High-risk tools require human approval before execution.
type ToolStore ¶
type ToolStore interface {
RegisterToolDescriptor(context.Context, RegisterToolDescriptorInput) (ToolDescriptor, error)
GetToolDescriptor(context.Context, string, string, string) (ToolDescriptor, error)
ListToolDescriptors(context.Context, string) ([]ToolDescriptor, error)
CreateToolCall(context.Context, CreateToolCallInput) (CreateToolCallResult, error)
GetToolCall(context.Context, string, uuid.UUID) (ToolCall, error)
UpdateToolCall(context.Context, UpdateToolCallInput) (ToolCall, error)
CreateToolApproval(context.Context, CreateToolApprovalInput) (CreateToolApprovalResult, error)
GetToolApproval(context.Context, string, uuid.UUID) (ToolApproval, error)
DecideToolApproval(context.Context, DecideToolApprovalInput) (ToolApproval, error)
}
type TransitionAttemptInput ¶
type TransitionWorkflowInput ¶
type TransitionWorkflowInput struct {
TenantID string
WorkflowID uuid.UUID
ExpectedVersion int64
To WorkflowStatus
FailureCode string
ExpectedOwner string
}
TransitionWorkflowInput CAS-transitions one workflow. ExpectedOwner, when non-empty, fences the transition to the orchestrator instance that holds a live claim: the write fails with ErrFenced when the claim was lost or expired. Empty disables the check (single-instance mode, non-claiming controllers).
type TransitionWorkflowStepInput ¶
type TransitionWorkflowStepInput struct {
TenantID string
WorkflowID uuid.UUID
StepName string
ExpectedVersion int64
To StepStatus
TaskID *uuid.UUID
AttemptCount *int
ResultSummary json.RawMessage
FailureCode string
ExpectedOwner string
}
TransitionWorkflowStepInput CAS-transitions one step. Zero fields are left unchanged; TaskID/AttemptCount set when provided. ExpectedOwner, when non-empty, fences the transition to the orchestrator instance that holds a live claim on the parent workflow (see TransitionWorkflowInput).
type UpdateRuntimePoolStatusInput ¶
type UpdateRuntimePoolStatusInput struct {
TenantID string
PoolID string
Status string
// OperatorSubject is the authenticated principal requesting the status
// change. It must hold a runtime_pool_operator_grants row for the pool;
// the tenant usage grant alone is never sufficient.
OperatorSubject string
ExpectedVersion int64
}
type UpdateToolCallInput ¶
type Workflow ¶
type Workflow struct {
ID uuid.UUID
TenantID string
Namespace string
IdempotencyKey string
Goal string
Spec json.RawMessage
Status WorkflowStatus
FailureCode string
CancelRequestedAt *time.Time
// Budget ceilings. Zero means the dimension is unbounded.
BudgetMaxTasks int64
BudgetMaxTokens int64
BudgetMaxCostMicroUSD money.MicroUSD
BudgetExhaustedAt *time.Time
DeadlineAt *time.Time
DeadlineExceededAt *time.Time
// NeedsBudgetReconciliation is set when a step's token/cost reservation may
// be understated relative to its derived task spec — e.g. after the 000028
// upgrade backfilled task-count slots but could not re-derive merged specs
// in pure SQL. While set, dynamic spawning is paused (a stale-low commitment
// could slip a spawn past a ceiling); the controller's reconcile loop
// re-derives the reservations and clears the flag.
NeedsBudgetReconciliation bool
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
Workflow is one durable workflow run.
type WorkflowStatus ¶
type WorkflowStatus string
WorkflowStatus is the lifecycle of one workflow run.
const ( WorkflowPending WorkflowStatus = "PENDING" WorkflowRunning WorkflowStatus = "RUNNING" WorkflowSucceeded WorkflowStatus = "SUCCEEDED" WorkflowFailed WorkflowStatus = "FAILED" WorkflowCancelled WorkflowStatus = "CANCELLED" )
func (WorkflowStatus) Terminal ¶
func (s WorkflowStatus) Terminal() bool
type WorkflowStep ¶
type WorkflowStep struct {
ID uuid.UUID
TenantID string
WorkflowID uuid.UUID
Name string
Ordinal int
Status StepStatus
AttemptCount int
TaskID *uuid.UUID
ResultSummary json.RawMessage
FailureCode string
DecidedBy string
ApprovalDecision string
DecidedAt *time.Time
ParentStepName string
SpawnDepth int
IsDynamic bool
SpawnKey string
Goal string
AgentVersionRef string
Spec json.RawMessage
MaxAttempts int
// Reserved* is the outstanding workflow budget reservation held by an
// undispatched or retrying step: the future Task's token/cost ceiling
// plus its task-count slot. It transfers to the task's own budget
// ledger at admission and returns to zero when the step reaches a
// terminal state without one.
ReservedTasks int64
ReservedTokens int64
ReservedCostMicroUSD money.MicroUSD
ResourceVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
WorkflowStep is one step of a workflow: a declared DAG node plus its dispatch state. AttemptCount drives the single-step retry budget. Dynamic Dynamic steps carry their whole definition here — declared steps keep theirs in the workflow document — with the spawning parent and depth lineage for the recursion guard.
type WorkflowStore ¶
type WorkflowStore interface {
CreateWorkflow(context.Context, CreateWorkflowInput) (CreateWorkflowResult, error)
GetWorkflow(context.Context, string, uuid.UUID) (Workflow, error)
// ListActiveWorkflows returns non-terminal workflows oldest-first for
// the orchestrator reconcile loop (all tenants; creation is where
// tenant scoping is enforced).
ListActiveWorkflows(context.Context, int) ([]Workflow, error)
ListWorkflowSteps(context.Context, string, uuid.UUID) ([]WorkflowStep, error)
GetWorkflowStep(context.Context, string, uuid.UUID, string) (WorkflowStep, error)
TransitionWorkflow(context.Context, TransitionWorkflowInput) (Workflow, error)
TransitionWorkflowStep(context.Context, TransitionWorkflowStepInput) (WorkflowStep, error)
DecideWorkflowStepApproval(context.Context, DecideWorkflowStepApprovalInput) (WorkflowStep, error)
// RequestWorkflowCancellation records the durable cancellation intent;
// the orchestrator propagates it to active steps and finalizes.
RequestWorkflowCancellation(context.Context, string, uuid.UUID, int64) (Workflow, error)
// ArtifactMetadata reads the digest, size and media type of one stored
// artifact URI so the orchestrator can open task result documents.
ArtifactMetadata(context.Context, string, string) ([]byte, int64, string, error)
// ClaimWorkflows leases active workflows to one orchestrator instance
// Expired claims are stolen, so a dead instance's workflows are
// taken over by its peers. Tenants are claimed round-robin.
ClaimWorkflows(context.Context, ClaimWorkflowsInput) ([]Workflow, error)
// SpawnWorkflowStep creates one dynamic step with all recursion, fan-out
// and budget guards applied in the same transaction. A spawn_key
// replay returns the existing step.
SpawnWorkflowStep(context.Context, SpawnWorkflowStepInput) (SpawnWorkflowStepResult, error)
// MarkWorkflowBudgetExhausted records the durable budget-stop intent.
MarkWorkflowBudgetExhausted(context.Context, string, uuid.UUID, int64) (Workflow, error)
// MarkWorkflowDeadlineExceeded records the durable deadline-stop intent.
MarkWorkflowDeadlineExceeded(context.Context, string, uuid.UUID, int64) (Workflow, error)
// WorkflowUsageSnapshot aggregates a workflow's task count and settled
// usage.
WorkflowUsageSnapshot(context.Context, string, uuid.UUID) (WorkflowUsage, error)
}
WorkflowStore is the durable workflow surface. The postgres Store satisfies it.
type WorkflowUsage ¶
type WorkflowUsage struct {
Tasks int64
Tokens int64
CostMicroUSD money.MicroUSD
ReservedTokens int64
ReservedCostMicroUSD money.MicroUSD
PendingOverage bool
BudgetMaxTasks int64
BudgetMaxTokens int64
BudgetMaxCostMicroUSD money.MicroUSD
// StepReserved* counts the workflow budget reservations still held by
// undispatched (or retrying) steps: the outstanding future commitment
// that exists before any task budget ledger does.
StepReservedTasks int64
StepReservedTokens int64
StepReservedCostMicroUSD money.MicroUSD
}
WorkflowUsage is the aggregated consumption of one workflow: tasks that carry its idempotency prefix plus their settled usage.
func (WorkflowUsage) CommittedCostMicroUSD ¶
func (u WorkflowUsage) CommittedCostMicroUSD() money.MicroUSD
CommittedCostMicroUSD returns settled plus task-reserved plus step-reserved cost: the workflow's total cost commitment.
func (WorkflowUsage) CommittedTasks ¶
func (u WorkflowUsage) CommittedTasks() int64
CommittedTasks returns the workflow's total task promise: created tasks plus the task slots reserved by undispatched steps.
func (WorkflowUsage) CommittedTokens ¶
func (u WorkflowUsage) CommittedTokens() int64
CommittedTokens returns settled plus task-reserved plus step-reserved tokens: the workflow's total token commitment.
func (WorkflowUsage) Exhausted ¶
func (u WorkflowUsage) Exhausted() bool
Exhausted reports whether any declared ceiling is met or exceeded by created tasks and their settled or task-reserved usage. Step reservations are excluded: a promise that exactly fills the budget must still run, and over-promising is already impossible because spawn and creation reserve inside their transactions.