Documentation
¶
Overview ¶
Package providerexecutor defines the provider-neutral execution contract for infrastructure lifecycle operations.
Authority ¶
The providerexecutor/v1beta1 wire format is authoritative for canonical digests, envelope validation, resource-graph invariants, and lifecycle transitions. The owning control plane, Techstack, authorizes commands and is authoritative for the operation ledger and its projections.
Non-authority ¶
The package does not select adapters, define provider capabilities, resolve credentials, own desired state, or decide product and billing policy. Executor is a seam for a control-plane-owned adapter, not a transfer of lifecycle or ledger authority to this package or to a conformance harness.
Side effects ¶
Validation, hashing, receipt assembly, and transition helpers perform no I/O. An injected EvidenceVerifier may perform bounded verification and must honor its context. An Executor implementation may perform provider side effects; the caller must persist the command and initial receipt before invoking it.
Persistence ¶
This package has no database, cache, or durable storage.
Concurrency ¶
Commands and receipts are immutable envelopes. Lease revision, runtime server, resource generation, provider, and capability snapshot fence every entry. The package provides no synchronization: the owning control plane must serialize or CAS ledger-head advancement and reject stale results.
Secrets ¶
Contract values must contain opaque lookup references and hashes only. Raw credentials, private keys, human diagnostics, provider responses, and secret-bearing desired specs must not be placed in commands, receipts, reasons, or evidence. Reasons contain only a machine-readable code and retryability; the provider.* namespace is closed by this contract.
Index ¶
- Constants
- Variables
- func CanTransition(operation Operation, from, to Phase) bool
- func ComputeCommandDigest(command Command) (string, error)
- func ComputeEvidenceSubjectHash(command Command, target ResourceTarget, observation ObservationState) string
- func ComputeNativeRefHash(nativeRef string) string
- func ComputeOperationID(tenantID, leaseID, resourceGenerationID string, operation Operation, ...) string
- func ComputeReceiptDigest(receipt Receipt) (string, error)
- func ComputeResourceGraphHash(targets []ResourceTarget) (string, error)
- func IsProviderReasonCode(code string) bool
- func ValidateAppend(ctx context.Context, command Command, previous, next Receipt, ...) error
- func ValidateReplay(original, replay Command) error
- func ValidateTransition(operation Operation, from, to Phase) error
- type CleanupState
- type Command
- type Evidence
- type EvidenceSource
- type EvidenceVerifier
- type ExecutionRequest
- type ExecutionResult
- type Executor
- type ObservationState
- type Operation
- type Phase
- type Reason
- type Receipt
- type ResourceBinding
- type ResourceDisposition
- type ResourceTarget
- type Status
- type WorkerExecution
- type WorkerExecutionResult
- type WorkerPhase
Constants ¶
const ( MaxTargets = 128 MaxResources = 256 MaxEvidencePerResource = 32 MaxEvidencePerReceipt = 512 // MaxJSONSafeInteger keeps revisions and receipt sequences exact in Go, // JavaScript, and JSON-backed projections. MaxJSONSafeInteger uint64 = 1<<53 - 1 )
The v1beta1 contract is intentionally bounded so validation, hashing, and graph traversal have predictable resource use. These bounds apply to one command or receipt envelope, not to TechStack's durable ledger retention.
const ( ReasonCodeProviderAuth = "provider.auth" ReasonCodeProviderPermission = "provider.permission" ReasonCodeProviderInvalidSpec = "provider.invalid_spec" ReasonCodeProviderQuota = "provider.quota" ReasonCodeProviderRateLimit = "provider.rate_limit" ReasonCodeProviderConflict = "provider.conflict" ReasonCodeProviderNotFound = "provider.not_found" ReasonCodeProviderTransient = "provider.transient" ReasonCodeProviderTimeout = "provider.timeout" ReasonCodeProviderPartialCreate = "provider.partial_create" ReasonCodeProviderCleanupRequired = "provider.cleanup_required" )
Canonical provider failure reason codes. Provider adapters must map native SDK and API failures into this closed taxonomy before returning a result; provider-specific diagnostics belong in secret-free evidence, logs, or support references rather than new wire-level reason codes.
const APIVersion = "providerexecutor/v1beta1"
APIVersion is the exact provider-executor contract version.
Variables ¶
var ( ErrInvalidCommand = errors.New("providerexecutor: invalid command") ErrInvalidReceipt = errors.New("providerexecutor: invalid receipt") ErrIdempotencyConflict = errors.New("providerexecutor: idempotency conflict") ErrAbsenceProofRequired = errors.New("providerexecutor: provider-native absence proof required") )
Validation errors classify rejected commands, receipts, replays, and unproven absence claims.
Functions ¶
func CanTransition ¶
CanTransition reports whether the owning ledger may append the next phase. It deliberately does not allow skipping absence_pending during decommission.
func ComputeCommandDigest ¶
ComputeCommandDigest hashes the immutable, idempotency-relevant command body. The digest field itself is excluded; RequestedAt remains part of the immutable authorization envelope and must not drift across retries.
func ComputeEvidenceSubjectHash ¶
func ComputeEvidenceSubjectHash(command Command, target ResourceTarget, observation ObservationState) string
ComputeEvidenceSubjectHash binds definitive evidence to the immutable command, resource ownership, and requested observation.
func ComputeNativeRefHash ¶
ComputeNativeRefHash binds evidence to one provider-native resource handle without copying that handle into an attestation subject.
func ComputeOperationID ¶
func ComputeOperationID(tenantID, leaseID, resourceGenerationID string, operation Operation, idempotencyKey string) string
ComputeOperationID derives the stable, generation-bound operation identity used for retries. Reusing an idempotency key in a later resource generation therefore cannot address or claim an earlier generation's ledger.
func ComputeReceiptDigest ¶
ComputeReceiptDigest hashes a receipt excluding ReceiptDigest.
func ComputeResourceGraphHash ¶
func ComputeResourceGraphHash(targets []ResourceTarget) (string, error)
ComputeResourceGraphHash derives the canonical digest of the immutable resource targets authorized by a command. Target order and surrounding whitespace do not affect the result; malformed targets are rejected before a digest is returned. An empty graph has a stable digest of the empty JSON array rather than a caller-selected placeholder.
func IsProviderReasonCode ¶
IsProviderReasonCode reports whether code is in the closed provider failure taxonomy. It returns false for policy, admission, or coordinator codes, which use their own non-provider namespaces.
func ValidateAppend ¶
func ValidateAppend(ctx context.Context, command Command, previous, next Receipt, verifier EvidenceVerifier) error
ValidateAppend verifies a receipt before appending it after previous. It enforces hash-chain, sequence, time, phase-transition, and resource-graph continuity in addition to the standalone receipt invariants.
func ValidateReplay ¶
ValidateReplay rejects reuse of an idempotency key for a different command.
func ValidateTransition ¶
ValidateTransition returns a descriptive error for an illegal ledger phase transition.
Types ¶
type CleanupState ¶
type CleanupState string
CleanupState reports whether a resource still requires cleanup work.
const ( CleanupNotRequired CleanupState = "not_required" CleanupRequired CleanupState = "required" CleanupPending CleanupState = "pending" CleanupComplete CleanupState = "complete" CleanupBlocked CleanupState = "blocked" )
Resource cleanup values accepted by the contract.
type Command ¶
type Command struct {
APIVersion string `json:"api_version"`
OperationID string `json:"operation_id"`
Operation Operation `json:"operation"`
TenantID string `json:"tenant_id"`
LeaseID string `json:"lease_id"`
LeaseRevision uint64 `json:"lease_revision"`
RuntimeServerID string `json:"runtime_server_id"`
ResourceGenerationID string `json:"resource_generation_id"`
IdempotencyKey string `json:"idempotency_key"`
ProviderID string `json:"provider_id"`
AdapterID string `json:"adapter_id"`
CustodyRef string `json:"custody_ref"`
CustodyHash string `json:"custody_hash"`
ConnectionRef string `json:"connection_ref"`
ConnectionHash string `json:"connection_hash"`
CapabilitySnapshotHash string `json:"capability_snapshot_hash"`
ExecutionProfileHash string `json:"execution_profile_hash"`
ResourceGraphHash string `json:"resource_graph_hash"`
LedgerRevision uint64 `json:"ledger_revision"`
DesiredSpecRef string `json:"desired_spec_ref,omitempty"`
DesiredSpecHash string `json:"desired_spec_hash,omitempty"`
Targets []ResourceTarget `json:"targets,omitempty"`
RequestedAt time.Time `json:"requested_at"`
CommandDigest string `json:"command_digest"`
}
Command is authorized and persisted by the owning product before it crosses an Executor boundary. AdapterID selects a TechStack-owned adapter; it is not a StackKit compatibility or architecture field. CustodyRef, ConnectionRef, and DesiredSpecRef are hierarchical server-side lookup references whose identifiers are opaque to this package; they must never contain raw credentials. LeaseRevision, RuntimeServerID, and ResourceGenerationID fence execution to the exact lease/server/generation aggregate that TechStack admitted. ProviderID is the stable vendor identity; AdapterID selects the TechStack implementation. CapabilitySnapshotHash and ExecutionProfileHash retain the exact catalog/admission decision used for this operation.
func SealCommand ¶
SealCommand normalizes a command, derives its operation ID and digest, and validates the resulting immutable envelope.
type Evidence ¶
type Evidence struct {
Ref string `json:"ref"`
Digest string `json:"digest"`
Source EvidenceSource `json:"source"`
OperationID string `json:"operation_id"`
LeaseRevision uint64 `json:"lease_revision"`
RuntimeServerID string `json:"runtime_server_id"`
ProviderID string `json:"provider_id"`
CapabilitySnapshotHash string `json:"capability_snapshot_hash"`
BindingID string `json:"binding_id"`
NativeRefHash string `json:"native_ref_hash"`
ConnectionHash string `json:"connection_hash"`
ExecutionProfileHash string `json:"execution_profile_hash"`
ResourceGraphHash string `json:"resource_graph_hash"`
SubjectHash string `json:"subject_hash"`
Observation ObservationState `json:"observation"`
Definitive bool `json:"definitive"`
AttestationRef string `json:"attestation_ref"`
AttestationDigest string `json:"attestation_digest"`
CollectedAt time.Time `json:"collected_at"`
}
Evidence is immutable observation evidence. Digest hashes the evidence payload retained by the owning product; Ref locates that payload without embedding it in the shared contract.
type EvidenceSource ¶
type EvidenceSource string
EvidenceSource identifies who made an observation. Only provider_api and provider_event evidence can prove absence; executor-local assertions cannot.
const ( EvidenceSourceProviderAPI EvidenceSource = "provider_api" EvidenceSourceProviderEvent EvidenceSource = "provider_event" EvidenceSourceAdapter EvidenceSource = "adapter" )
Evidence source values accepted by the contract.
type EvidenceVerifier ¶
type EvidenceVerifier interface {
VerifyEvidence(context.Context, Command, ResourceTarget, Evidence) error
}
EvidenceVerifier verifies the attestation behind definitive provider-native evidence. TechStack owns the implementation and its trust configuration. Implementations must honor context cancellation. The shared package invokes it before accepting an absent lifecycle state and rejects typed-nil verifiers.
type ExecutionRequest ¶
type ExecutionRequest struct {
Command Command `json:"command"`
Previous Receipt `json:"previous"`
}
ExecutionRequest gives an adapter the command and the validated current ledger head. The adapter therefore has the prior lifecycle phase, complete resource graph, and immutable evidence history it needs to return exactly one next transition. The request does not transfer ledger authority: only TechStack's coordinator may seal and persist the resulting receipt.
func (ExecutionRequest) Validate ¶
func (request ExecutionRequest) Validate(ctx context.Context, verifier EvidenceVerifier) error
Validate confirms that a coordinator is giving an adapter one sealed command and the current, valid receipt from that command's ledger chain.
type ExecutionResult ¶
type ExecutionResult struct {
Status Status `json:"status"`
Phase Phase `json:"phase"`
Resources []ResourceBinding `json:"resources,omitempty"`
Reason *Reason `json:"reason,omitempty"`
}
ExecutionResult is the unchained result of one adapter invocation. It has no receipt identity, sequence, or digest because an adapter cannot safely own TechStack's ledger head. A provider failure is represented by a failed result with a closed provider reason and every known resource binding. Admission and policy failures use DenyReceipt before invocation. The single-return shape prevents callers from discarding partial-create cleanup handles on a conventional error path.
type Executor ¶
type Executor interface {
Execute(context.Context, ExecutionRequest) ExecutionResult
}
Executor is intentionally transport-agnostic. It returns an unchained ExecutionResult, never an authoritative ledger receipt. TechStack's coordinator owns the ledger head, calls AssembleReceipt, persists the sealed receipt, and validates the append before advancing projections.
type ObservationState ¶
type ObservationState string
ObservationState reports provider-native resource presence.
const ( ObservationPresent ObservationState = "present" ObservationAbsent ObservationState = "absent" ObservationUnknown ObservationState = "unknown" )
Provider resource observation values accepted by the contract.
type Phase ¶
type Phase string
Phase is the durable lifecycle phase recorded by the owning control plane. Failed and denied are terminal phases. Absent is also a terminal result for observe and decommission, but its meaning is operation-specific: observe proves that every target is absent without asserting a delete workflow; decommission reaches absent only after delete acceptance, absence_pending, definitive absence evidence, and complete cleanup.
const ( PhaseRequested Phase = "requested" PhaseAccepted Phase = "accepted" PhasePlanned Phase = "planned" PhaseResourcesBound Phase = "resources_bound" PhasePresent Phase = "present" PhaseDeleteAccepted Phase = "delete_accepted" PhaseAbsencePending Phase = "absence_pending" PhaseAbsent Phase = "absent" PhaseFailed Phase = "failed" PhaseDenied Phase = "denied" )
Durable lifecycle phases accepted by the contract.
type Reason ¶
Reason is a secret-free, machine-readable failure envelope. Human-readable diagnostics and raw provider responses remain in TechStack-owned logs or evidence stores and never cross this contract.
type Receipt ¶
type Receipt struct {
APIVersion string `json:"api_version"`
OperationID string `json:"operation_id"`
Operation Operation `json:"operation"`
TenantID string `json:"tenant_id"`
LeaseID string `json:"lease_id"`
LeaseRevision uint64 `json:"lease_revision"`
RuntimeServerID string `json:"runtime_server_id"`
ResourceGenerationID string `json:"resource_generation_id"`
IdempotencyKey string `json:"idempotency_key"`
ProviderID string `json:"provider_id"`
AdapterID string `json:"adapter_id"`
CapabilitySnapshotHash string `json:"capability_snapshot_hash"`
CommandDigest string `json:"command_digest"`
DesiredSpecHash string `json:"desired_spec_hash,omitempty"`
Sequence uint64 `json:"sequence"`
PreviousReceiptDigest string `json:"previous_receipt_digest,omitempty"`
Status Status `json:"status"`
Phase Phase `json:"phase"`
PhaseEnteredAt time.Time `json:"phase_entered_at"`
Resources []ResourceBinding `json:"resources,omitempty"`
Reason *Reason `json:"reason,omitempty"`
IssuedAt time.Time `json:"issued_at"`
ReceiptDigest string `json:"receipt_digest"`
}
Receipt is an immutable lifecycle-ledger entry. TechStack's coordinator first persists sequence 1 as pending/requested with no resources, then asks an Executor to return later entries (normally starting at sequence 2). The coordinator seals, validates, and appends each entry. Sequence and PreviousReceiptDigest form the validated append chain. ReceiptDigest detects accidental mutation; it is not a replacement for transport authentication or durable-ledger integrity. Every receipt repeats the command's exact lease revision, runtime server, provider, capability snapshot, and resource generation so a ledger chain cannot cross an admitted execution fence.
func AssembleReceipt ¶
func AssembleReceipt(ctx context.Context, request ExecutionRequest, result ExecutionResult, issuedAt time.Time, verifier EvidenceVerifier) (Receipt, error)
AssembleReceipt has no storage side effect. It lets TechStack's coordinator turn an adapter result into the next immutable receipt using the coordinator ledger head. Callers must persist the result only after this function succeeds; it seals and validates the candidate and its append transition.
func DenyReceipt ¶
func DenyReceipt(ctx context.Context, request ExecutionRequest, reason Reason, issuedAt time.Time, verifier EvidenceVerifier) (Receipt, error)
DenyReceipt creates the only valid denied entry without invoking an Executor. The durable head must still be pending/requested, proving that admission stopped before provider-side-effect custody began.
func InitialReceipt ¶
InitialReceipt creates the coordinator-owned head of a new lifecycle chain. It is the only valid sequence-1 receipt. TechStack persists it before calling an Executor, then passes it to the executor as read-only execution context in an ExecutionRequest. The executor never mutates the ledger head.
func (Receipt) ValidateFor ¶
func (receipt Receipt) ValidateFor(ctx context.Context, command Command, verifier EvidenceVerifier) error
ValidateFor verifies receipt identity, graph integrity, lifecycle semantics, and attested provider-native evidence for every claimed absence.
type ResourceBinding ¶
type ResourceBinding struct {
BindingID string `json:"binding_id"`
Kind string `json:"kind"`
NativeRef string `json:"native_ref"`
ParentBindingID string `json:"parent_binding_id,omitempty"`
OwnershipHash string `json:"ownership_hash"`
Disposition ResourceDisposition `json:"disposition"`
Observation ObservationState `json:"observation"`
Cleanup CleanupState `json:"cleanup"`
Evidence []Evidence `json:"evidence,omitempty"`
}
ResourceBinding is one node in the authoritative resource graph. NativeRef is retained through cleanup so a partially-created operation remains recoverable and an absent resource can still be audited.
type ResourceDisposition ¶
type ResourceDisposition string
ResourceDisposition declares the cleanup action for a bound resource.
const ( // DispositionDelete requires the owning ledger to retain and delete the // resource before a decommission operation may complete. DispositionDelete ResourceDisposition = "delete" )
type ResourceTarget ¶
type ResourceTarget struct {
BindingID string `json:"binding_id"`
Kind string `json:"kind"`
NativeRef string `json:"native_ref"`
ParentBindingID string `json:"parent_binding_id,omitempty"`
OwnershipHash string `json:"ownership_hash"`
Disposition ResourceDisposition `json:"disposition"`
}
ResourceTarget identifies an already-known provider resource without exposing credentials or provider-specific configuration.
type WorkerExecution ¶
type WorkerExecution struct {
Command Command `json:"command"`
InvocationID string `json:"invocation_id"`
WorkerID string `json:"worker_id"`
HeadSequence uint64 `json:"head_sequence"`
HeadDigest string `json:"head_digest"`
Phase WorkerPhase `json:"phase"`
Stage string `json:"stage,omitempty"`
Prerequisite *WorkerExecutionResult `json:"prerequisite,omitempty"`
Payload json.RawMessage `json:"payload,omitempty"`
TaskRef string `json:"task_ref,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
}
WorkerExecution is a bounded dispatch to a customer-owned executor. The original admitted command remains the authority; this envelope cannot grant a lease or a credential. Payload is the exact desired-spec document retained by the admitting product, never an argv list or credential transport.
func (WorkerExecution) Validate ¶
func (w WorkerExecution) Validate(now time.Time) error
Validate checks dispatch integrity and bounded lifetime. Credential custody, live lease revision and invocation admission are revalidated by the owning product immediately before dispatch; a valid envelope alone is not authority.
type WorkerExecutionResult ¶
type WorkerExecutionResult struct {
InvocationID string `json:"invocation_id"`
CommandDigest string `json:"command_digest"`
TaskRef string `json:"task_ref,omitempty"`
Accepted bool `json:"accepted"`
Complete bool `json:"complete"`
Succeeded bool `json:"succeeded"`
Observation json.RawMessage `json:"observation,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
}
WorkerExecutionResult reports only observed execution facts. Accepted is not completion: TaskRef must be observed separately before convergence is claimed.
type WorkerPhase ¶
type WorkerPhase string
const ( WorkerPhaseSubmit WorkerPhase = "submit" WorkerPhaseObserve WorkerPhase = "observe" )