Documentation
¶
Overview ¶
Package db is where the state lives.
PostgreSQL holds the runs, the steps, the tasks, the approvals, the workflows and their versions, the artifact references and the runner inventory. It does not hold an envelope or a log: the documentation is explicit that it "keeps only their digests and URIs", and the bytes are in the object store, which is package artifact's business.
Nothing in package graph or package driver may import this. Those two stay importable libraries "with no server, no bus and no database behind them", which is what makes agk run --local the same code path a server run takes instead of a second implementation that drifts. A test holds that boundary from the other side.
The namespace is carried by the database, not by discipline ¶
"Object keys are prefixed by namespace, and every query path carries the namespace so that a missing filter fails closed rather than returning another tenant's rows."
Fails closed is a stronger promise than is filtered, and a forgotten WHERE in Go is a full table read rather than an empty one. So the rule is not a convention this package asks callers to follow: a Pool cannot issue a statement at all. It hands out three doors, each of which binds something before any query runs, and row level security on every namespaced table reads what was bound.
In one namespace, bound for the transaction. The ordinary door.
Installation no namespace, for the work that legitimately has none, with the
reason named at the call site.
Session one pinned connection, for the two things a transaction cannot hold.
With nothing bound, current_setting answers null, the policy predicate is null, and a read returns no rows. Not an error, not another tenant's rows: nothing. A write stamped with a namespace other than the one bound is refused by the same policy's check, so a row cannot be planted in a namespace the caller is not in either.
The policy is FORCE, so it applies to the role that owns the tables as well, and Open refuses a connection whose role bypasses row level security, because a policy a superuser walks through is a policy that protects nothing on the installation that matters.
So an installation holds two addresses. The privileged one migrates, and Provision, which applies the migrations through it, also creates the role the other names: LOGIN NOSUPERUSER NOBYPASSRLS, owning nothing, granted read and write on the tables and read on the migration record, and nothing more. The API and the controller connect as that role, and a test does too.
Installation is a door and not a loophole ¶
Three things in the documentation have no namespace and would read an empty database without it: the controller "sweeps for actionable work on a fixed interval", which is the correctness guarantee of the whole scheduler; the three purges and the collector run across the installation; and a heartbeat "covers every in-flight task on that host", which is one host across several namespaces. Each call names its Reason, the set is small and closed, and a test counts the call sites, so an escape is something somebody added on purpose and can be read back rather than a habit.
Session is the third door ¶
Two things the documentation requires are properties of a connection and not of a transaction. The controller is elected by "a session-level PostgreSQL advisory lock", which "is held until explicitly released or the session ends", and it listens: "the API signals the controller with NOTIFY" and the controller holds LISTEN. A pooled connection handed back after a transaction would carry a LISTEN into the next caller and would drop the lock the moment it was recycled. Session pins one connection for the life of the holder and is not a door a namespaced handle can borrow.
The artifact, the envelope and the log ¶
The chapter draws one line through all three: "Envelopes and logs are not stored in the database: it keeps only their digests and URIs." So what is here is a digest, a URI, a size and a count, and the bytes are package artifact's.
An artifact is a reference and an object, which the schema splits because expiry does: "Expiry applies to the reference, never to the object. The row in artifacts binding a run, a step and a port to a digest is what is dropped; the physical sha256/<digest> object is collected once its reference count reaches zero, and not before." A reference that has been dropped is kept rather than deleted, so that a later request can be answered 410 and not 404, and it carries its own size and media type: it has to outlive the object it names.
An envelope is counted in the same place, for the reason two runs share an object in the first place. Two steps publishing identical bytes publish one object, so an envelope purge that deleted by digest alone would delete what another step still names. There is one counter for every kind of object rather than one per kind.
A log is neither. One task wrote it, nothing else names it, and the row keeps the URI, the line count and whether it was capped. Purging one is a deletion and not a decrement.
What this package does not settle ¶
A wrong namespace is not a missing one. Every mechanism here checks that a namespace is bound and none checks that it is the right one: In(ctx, whateverTheRequestAsked) passes the handle, the policy and every test. The value has to come from the authorisation decision and never from what a request asserted about itself, which is one rule left to a reviewer, and one is a number a reviewer can hold.
Index ¶
- Constants
- Variables
- func CanonicalImage(image string) string
- func CheckRef(ref string) error
- func Connect(ctx context.Context, url string) (*pgx.Conn, error)
- func Migrate(ctx context.Context, conn *pgx.Conn) ([]string, error)
- func MigrateThrough(ctx context.Context, conn *pgx.Conn, last string) ([]string, error)
- func Provision(ctx context.Context, admin *pgx.Conn, role, password string) ([]string, error)
- func WithKeepalives(conn string) string
- type APIToken
- type Activity
- type ActivityBucket
- type Administrator
- type Armed
- type ArtifactSummary
- type Attribution
- type AuditQuery
- type AuditRecordDisagrees
- type AuditTrail
- func (a AuditTrail) After(ctx context.Context, seq int64, limit int) ([]audit.Entry, error)
- func (a AuditTrail) Exported(ctx context.Context) (int64, []byte, error)
- func (a AuditTrail) MarkExported(ctx context.Context, seq int64, hash []byte) error
- func (a AuditTrail) Verify(ctx context.Context, batch int) (AuditVerification, error)
- type AuditVerification
- type AuthPolicy
- type Beaten
- type Beating
- type Bin
- type Bootstrap
- type BrickManifest
- type Buckets
- type Called
- type Caller
- type Ceilings
- type Challenge
- type Change
- type ChangeKind
- type ChangeRefused
- type Consumption
- type Containment
- type Credential
- type Decision
- type Declaration
- type DeletedPurge
- type Dispatch
- type Due
- type EnrolmentCode
- type Entry
- type Envelope
- type EnvelopeRef
- type Evaluation
- type Event
- type ExchangeCode
- type ExitCodeCount
- type Firing
- type GrantFile
- type GrantInput
- type GrantScope
- type GrantSecret
- type Granted
- type Group
- type Hook
- type HookCredential
- type HookTaken
- type ImagePin
- type Images
- type ImagesRecorded
- type JoinToken
- type Joined
- type Joining
- type Kind
- type LatestRun
- type LibraryFiles
- type Listed
- type ListedRun
- type ListedWorkflow
- type Listening
- type LiveChange
- type Log
- type LogChunk
- type Loss
- type ManifestRecorded
- type Memo
- type MemoPort
- type Migration
- type Move
- type MoveObjects
- type Moved
- type MovedObject
- type NS
- func (n *NS) AccessGrants(ctx context.Context) ([]access.Grant, error)
- func (n *NS) AccessGrantsAt(ctx context.Context, workflow string, now time.Time) ([]access.Grant, error)
- func (n *NS) AccessGrantsFor(ctx context.Context, p access.Principal, workflow string, now time.Time) ([]access.Grant, error)
- func (n *NS) Arm(ctx context.Context, workflow, commit string, entries []Entry, by string, ...) error
- func (n *NS) ArmedBy(ctx context.Context, workflow string) ([]Armed, error)
- func (n *NS) ArmedCommit(ctx context.Context, workflow string) (string, error)
- func (n *NS) Audit(ctx context.Context, r audit.Record) error
- func (n *NS) CheckVersion(ctx context.Context, v Version) error
- func (n *NS) ContextOf(ctx context.Context, run agk.RunID) (TriggerContext, error)
- func (n *NS) CreateRun(ctx context.Context, r NewRun) error
- func (n *NS) CreateWorkflow(ctx context.Context, name, branch string, protected bool, by string, ...) (WorkflowRecord, error)
- func (n *NS) Declaration(ctx context.Context, name string) (Declaration, error)
- func (n *NS) Declarations(ctx context.Context) ([]Declaration, error)
- func (n *NS) Declare(ctx context.Context, d Declaration) (Declaration, bool, error)
- func (n *NS) DefaultCommit(ctx context.Context, workflow string) (string, error)
- func (n *NS) DeleteWorkflow(ctx context.Context, workflow, by string, at time.Time) ([]agk.RunID, error)
- func (n *NS) Deleted(ctx context.Context, workflow string) (bool, error)
- func (n *NS) Delivered(ctx context.Context, u agk.URI, held time.Time) error
- func (n *NS) Delivery(ctx context.Context, path, method, id string, at time.Time, ...) (agk.RunID, bool, error)
- func (n *NS) DeliveryRun(ctx context.Context, path, method, id string, run agk.RunID) error
- func (n *NS) EventFired(ctx context.Context, l Listening, at time.Time, run agk.RunID, skipped string) error
- func (n *NS) EventRuns(ctx context.Context, source, id string, runs int) error
- func (n *NS) EventTaken(ctx context.Context, source, id, publisher string, at time.Time, ...) (int, bool, error)
- func (n *NS) Fired(ctx context.Context, d Due, f Firing) error
- func (n *NS) FirstLoad(ctx context.Context, before time.Time) (time.Time, error)
- func (n *NS) ForgetSealed(ctx context.Context, name string) error
- func (n *NS) FormerNames(ctx context.Context) ([]string, error)
- func (n *NS) GitHosted(ctx context.Context, workflow string) (bool, error)
- func (n *NS) GrantAccess(ctx context.Context, g access.Grant) error
- func (n *NS) Held(ctx context.Context, d Due) error
- func (n *NS) HoldRepository(ctx context.Context, workflow string) error
- func (n *NS) Hook(ctx context.Context, path, method string) (Hook, error)
- func (n *NS) HookCredential(ctx context.Context, workflow, path, method string) (HookCredential, error)
- func (n *NS) HookCredentials(ctx context.Context, workflow string) (map[[2]string]HookCredential, error)
- func (n *NS) HookHolder(ctx context.Context, workflow, path, method string) (string, error)
- func (n *NS) HookRefused(ctx context.Context, path, method string, at time.Time) error
- func (n *NS) ImagesOf(ctx context.Context, workflow string, named *Images) ([]ImagePin, []BrickManifest, error)
- func (n *NS) LogChunks(ctx context.Context, row string, after, limit int) ([]LogChunk, error)
- func (n *NS) MakeRoom(ctx context.Context, u Upload) (Room, error)
- func (n *NS) Manifest(ctx context.Context, workflow, image string) ([]byte, error)
- func (n *NS) Moving(ctx context.Context, workflow string) error
- func (n *NS) Namespace() string
- func (n *NS) NamespaceVarsOf(ctx context.Context, run agk.RunID) (map[string]any, error)
- func (n *NS) NotWritten(ctx context.Context, w Writing) error
- func (n *NS) NotifyRun(ctx context.Context, run agk.RunID) error
- func (n *NS) Output(ctx context.Context, run agk.RunID, name string) (Output, error)
- func (n *NS) PackLive(ctx context.Context, workflow, name string) error
- func (n *NS) Pin(ctx context.Context, workflow, reference string) (string, error)
- func (n *NS) Present(ctx context.Context, workflow string) error
- func (n *NS) PublishedPorts(ctx context.Context, run agk.RunID, step agk.Step) (Ports, error)
- func (n *NS) QuotaStatistics(ctx context.Context, b Buckets) ([]QuotaBucket, error)
- func (n *NS) ReceivePack(ctx context.Context, workflow string, p Pack) (string, error)
- func (n *NS) RecordImages(ctx context.Context, workflow, by string, at time.Time, images Images) (ImagesRecorded, error)
- func (n *NS) Release(ctx context.Context, u agk.URI, held time.Time) error
- func (n *NS) RemoveVariable(ctx context.Context, name string) error
- func (n *NS) RenameWorkflow(ctx context.Context, workflow, to string) error
- func (n *NS) Repacked(ctx context.Context, workflow, name string, replaced []string) error
- func (n *NS) Repository(ctx context.Context, workflow string) (Repository, error)
- func (n *NS) RequestCancel(ctx context.Context, run agk.RunID, at time.Time) (agk.RunState, bool, error)
- func (n *NS) Reserve(ctx context.Context, u agk.URI, hold time.Duration) (Resolved, time.Time, error)
- func (n *NS) Resolve(ctx context.Context, u agk.URI) (Resolved, error)
- func (n *NS) ResolveRef(ctx context.Context, workflow, ref string) (string, error)
- func (n *NS) RevokeAccess(ctx context.Context, workflow, id string) (access.Grant, error)
- func (n *NS) RunDetail(ctx context.Context, run agk.RunID) (RunDetail, error)
- func (n *NS) RunState(ctx context.Context, run agk.RunID) (agk.RunState, error)
- func (n *NS) SaveVersion(ctx context.Context, v Version) (Saved, error)
- func (n *NS) SaveVersions(ctx context.Context, vs []Version) ([]Saved, error)
- func (n *NS) SaveWorkflow(ctx context.Context, name, branch string) error
- func (n *NS) SealedValue(ctx context.Context, name string) (SealedValue, error)
- func (n *NS) SetDefault(ctx context.Context, workflow string, branch *string, protected *bool) (WorkflowRecord, WorkflowRecord, error)
- func (n *NS) SetVariable(ctx context.Context, v Variable) (Variable, bool, error)
- func (n *NS) StepInput(ctx context.Context, run agk.RunID, step agk.Step, attempt, shard int, ...) (Envelope, error)
- func (n *NS) StepLog(ctx context.Context, run agk.RunID, step agk.Step, since string, limit int) (StepLog, error)
- func (n *NS) StepOutput(ctx context.Context, run agk.RunID, step agk.Step, port agk.Port) (Envelope, error)
- func (n *NS) Storage(ctx context.Context) (string, error)
- func (n *NS) Stored(ctx context.Context, r Room, size int64) error
- func (n *NS) TaskLog(ctx context.Context, row string) (TaskLog, []LogChunk, error)
- func (n *NS) TellOwners(ctx context.Context, what Widening) ([]string, error)
- func (n *NS) Tree(ctx context.Context, workflow, commit string) ([]TreeFile, error)
- func (n *NS) TreeVersions(ctx context.Context, workflow, from string, limit int) ([]Listed, string, error)
- func (n *NS) Undeclare(ctx context.Context, name string) error
- func (n *NS) Unwritten(ctx context.Context, r Room) error
- func (n *NS) UpdateRefs(ctx context.Context, workflow, by string, at time.Time, updates []RefUpdate) error
- func (n *NS) Uploading(ctx context.Context, digest string, until time.Time) (Writing, error)
- func (n *NS) Variable(ctx context.Context, name string) (Variable, error)
- func (n *NS) Variables(ctx context.Context) ([]Variable, error)
- func (n *NS) VariablesFor(ctx context.Context, workflow string) (map[string]any, error)
- func (n *NS) Version(ctx context.Context, workflow, commit string) (Version, error)
- func (n *NS) VersionsAt(ctx context.Context, workflow string, commits []string) (map[string]Listed, error)
- func (n *NS) WorkflowRecord(ctx context.Context, name string) (WorkflowRecord, error)
- func (n *NS) WriteArtifact(ctx context.Context, r Reference) (Written, error)
- func (n *NS) WriteHookCertificate(ctx context.Context, workflow, path, method, by string, sum []byte) error
- func (n *NS) WriteHookSecret(ctx context.Context, workflow, path, method, by string, ...) error
- func (n *NS) WriteSealed(ctx context.Context, name string, seal func(version int) (SealedValue, error)) error
- type NameHeld
- type Namespace
- type NamespaceHolds
- type NewRun
- type NoRoom
- type NoRoomToMove
- type Notification
- type Object
- type Occupancy
- type Orphan
- type Output
- type Pack
- type Percentiles
- type PinMoved
- type Pool
- func (p *Pool) AskMove(ctx context.Context, namespace, workflow, target, by string, at time.Time, ...) error
- func (p *Pool) AuditTrail() AuditTrail
- func (p *Pool) BeginTerm(ctx context.Context, holder string) (Term, error)
- func (p *Pool) Close()
- func (p *Pool) Collectable(ctx context.Context, grace time.Duration, batch int) ([]Object, error)
- func (p *Pool) CollectablePacks(ctx context.Context, grace time.Duration, batch int) ([]RepositoryPack, error)
- func (p *Pool) Collected(ctx context.Context, objects []Object) (int, error)
- func (p *Pool) Collecting(ctx context.Context, claimed []Object, ...) ([]Object, error)
- func (p *Pool) CompleteMove(ctx context.Context, m Move, copied MoveObjects, grace time.Duration) (Moved, error)
- func (p *Pool) Current(ctx context.Context) error
- func (p *Pool) CurrentName(ctx context.Context, name string) (string, error)
- func (p *Pool) ExpireArtifacts(ctx context.Context, batch int) (int, error)
- func (p *Pool) ExpiredLogs(ctx context.Context, batch int) ([]Log, error)
- func (p *Pool) In(ctx context.Context, namespace string, fn func(context.Context, *NS) error) error
- func (p *Pool) Installation(ctx context.Context, reason Reason, fn func(context.Context, *Wide) error) error
- func (p *Pool) LiveEnvelopes(ctx context.Context, namespace string) ([]string, error)
- func (p *Pool) LogsGone(ctx context.Context, batch int) (int, error)
- func (p *Pool) LogsPurged(ctx context.Context, logs []Log) (int, error)
- func (p *Pool) MovedObjectsDue(ctx context.Context, batch int) ([]MovedObject, error)
- func (p *Pool) MovedObjectsGone(ctx context.Context, gone []MovedObject) error
- func (p *Pool) Moves(ctx context.Context, batch int) ([]Move, error)
- func (p *Pool) ObjectsOf(ctx context.Context, m Move) (MoveObjects, error)
- func (p *Pool) Orphaned(ctx context.Context, namespace string, orphans []Orphan) (int, error)
- func (p *Pool) PacksCollected(ctx context.Context, packs []RepositoryPack) (int, error)
- func (p *Pool) PurgeDeleted(ctx context.Context, batch int) (DeletedPurge, bool, error)
- func (p *Pool) PurgeEnvelopes(ctx context.Context, batch int) (int, error)
- func (p *Pool) PurgeUploads(ctx context.Context, batch int) (int, error)
- func (p *Pool) RecordUnrecorded(ctx context.Context, runs []Recording) (Recorded, error)
- func (p *Pool) Repackable(ctx context.Context, most, batch int) ([]Target, error)
- func (p *Pool) Session(ctx context.Context, fn func(context.Context, *pgxpool.Conn) error) error
- func (p *Pool) Storage(ctx context.Context, name string) (string, error)
- func (p *Pool) Sweepable(ctx context.Context) ([]string, error)
- func (p *Pool) Unnamed(ctx context.Context, namespace string, digests []string) ([]string, error)
- func (p *Pool) UnrecordedRuns(ctx context.Context, after Unrecorded, batch int) ([]Unrecorded, error)
- func (p *Pool) WatchLive(ctx context.Context, on func(LiveChange)) error
- func (p *Pool) WatchLogs(ctx context.Context, sweep time.Duration, on func(agk.TaskID)) error
- type PoolSeries
- type Ports
- type Profile
- type QuotaBucket
- type Quotas
- type Reason
- type Recorded
- type Recording
- type Redeemed
- type Ref
- type RefUnresolved
- type RefUpdate
- type Reference
- type RenameWaits
- type Repository
- type RepositoryPack
- type Resolved
- type Revocation
- type Room
- type Rotated
- type Rotating
- type RunBucket
- type RunDetail
- type RunInclude
- type RunQuery
- type RunSummary
- type RunTrace
- type Runner
- type RunnerPool
- type RunnerSeries
- type RunnerSilence
- type RunsPerHourReached
- type Saved
- type SealedValue
- type ServiceAccount
- type Session
- type SharedOutputs
- type SlotBucket
- type Status
- type StepBucket
- type StepLog
- type StepRow
- type StepStrip
- type StepSummary
- type Stopped
- type TOTPEnrolment
- type Target
- type TaskLog
- type TaskRow
- type TaskSummary
- type Term
- type TooManyChallenges
- type TracedDispatch
- type TreeFile
- type TriggerContext
- type Unarmed
- type Unrecorded
- type Upload
- type User
- type Variable
- type VariablesFull
- type Version
- type Wide
- func (w *Wide) AccessGrantsAcross(ctx context.Context, p access.Principal, now time.Time) ([]access.Grant, error)
- func (w *Wide) Actionable(ctx context.Context, now time.Time, batch int) ([]agk.RunID, error)
- func (w *Wide) ActivityStatistics(ctx context.Context, b Buckets) ([]ActivityBucket, Activity, error)
- func (w *Wide) AddCredential(ctx context.Context, c Credential) error
- func (w *Wide) AddMember(ctx context.Context, group, login string) (bool, error)
- func (w *Wide) Administrators(ctx context.Context) ([]Administrator, error)
- func (w *Wide) Attribution(ctx context.Context, namespace, workflow, principal string) (Attribution, error)
- func (w *Wide) Audit(ctx context.Context, r audit.Record) error
- func (w *Wide) AuditEntries(ctx context.Context, seq int64, limit int) ([]audit.Entry, error)
- func (w *Wide) AuditHead(ctx context.Context) (int64, []byte, error)
- func (w *Wide) AuditIn(ctx context.Context, namespace string, r audit.Record) error
- func (w *Wide) AuditPage(ctx context.Context, q AuditQuery) (entries []audit.Entry, head, verified int64, err error)
- func (w *Wide) Authenticate(ctx context.Context, credential string, now time.Time) (Runner, error)
- func (w *Wide) Avatar(ctx context.Context, login string) ([]byte, time.Time, error)
- func (w *Wide) Beat(ctx context.Context, runner string, b Beating, at time.Time) (Beaten, error)
- func (w *Wide) BindUnredeemed(ctx context.Context, namespace string, key agk.TaskID, row, runner string) (string, error)
- func (w *Wide) Bootstrap(ctx context.Context) (Bootstrap, error)
- func (w *Wide) BootstrapHeld(ctx context.Context) (Bootstrap, error)
- func (w *Wide) CalledBy(ctx context.Context, task agk.TaskID) (Called, error)
- func (w *Wide) CancelCalled(ctx context.Context, run agk.RunID, task agk.TaskID, at time.Time) error
- func (w *Wide) CancelTasks(ctx context.Context, namespace string, run agk.RunID, at time.Time) ([]agk.TaskID, error)
- func (w *Wide) Consumption(ctx context.Context) ([]Consumption, error)
- func (w *Wide) CreateGroup(ctx context.Context, name string) error
- func (w *Wide) CreateNamespace(ctx context.Context, n Namespace) (bool, error)
- func (w *Wide) CreateRunnerPool(ctx context.Context, p RunnerPool) error
- func (w *Wide) CreateServiceAccount(ctx context.Context, s ServiceAccount) error
- func (w *Wide) CreateUser(ctx context.Context, u User) error
- func (w *Wide) Credential(ctx context.Context, id string) (Credential, error)
- func (w *Wide) CredentialUsed(ctx context.Context, id string, at time.Time) error
- func (w *Wide) CredentialsOf(ctx context.Context, login string) ([]Credential, error)
- func (w *Wide) CurrentName(ctx context.Context, name string) (string, error)
- func (w *Wide) DeletedAmong(ctx context.Context, workflows [][2]string) (map[[2]string]bool, error)
- func (w *Wide) Delivered(ctx context.Context, events []Event, at time.Time) (int, error)
- func (w *Wide) DismissNotification(ctx context.Context, recipient, id string, now time.Time) error
- func (w *Wide) Drain(ctx context.Context, runner, by, why string, at time.Time) (Runner, error)
- func (w *Wide) DueSchedules(ctx context.Context, now time.Time, batch int) ([]Due, error)
- func (w *Wide) EndBootstrap(ctx context.Context, at time.Time) (bool, error)
- func (w *Wide) EndSession(ctx context.Context, hash []byte, at time.Time) (bool, error)
- func (w *Wide) EndSessionsOpenedBy(ctx context.Context, login, credential string, kept []byte, at time.Time) (int, error)
- func (w *Wide) EndTOTPEnrolment(ctx context.Context, login, id string) error
- func (w *Wide) EndTasks(ctx context.Context, namespace string, run agk.RunID, at time.Time) ([]agk.TaskID, error)
- func (w *Wide) EnrolmentCodeByHash(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, error)
- func (w *Wide) Fence(ctx context.Context, token int64) error
- func (w *Wide) FirstCapacity(ctx context.Context, before time.Time) (time.Time, error)
- func (w *Wide) FirstRun(ctx context.Context, among []Workflow, before time.Time) (time.Time, error)
- func (w *Wide) FirstRunAnywhere(ctx context.Context, before time.Time) (time.Time, error)
- func (w *Wide) Forget(ctx context.Context, namespace, key string) error
- func (w *Wide) GiveBuiltInIdentities(ctx context.Context) ([]string, error)
- func (w *Wide) GrantAccess(ctx context.Context, g access.Grant) error
- func (w *Wide) Group(ctx context.Context, name string) (Group, error)
- func (w *Wide) Groups(ctx context.Context) ([]Group, error)
- func (w *Wide) GroupsOf(ctx context.Context, login string) ([]string, error)
- func (w *Wide) HeldBy(ctx context.Context, namespace string, key agk.TaskID, row string) (string, error)
- func (w *Wide) HoldBootstrapToEnd(ctx context.Context) (Bootstrap, error)
- func (w *Wide) HoldMember(ctx context.Context, login string) error
- func (w *Wide) HoldUser(ctx context.Context, login string) (User, error)
- func (w *Wide) Holding(ctx context.Context, namespace, group string) (agk.RunID, error)
- func (w *Wide) ImportBootstrapToken(ctx context.Context, hash []byte) (bool, error)
- func (w *Wide) InstallationPolicy(ctx context.Context) (AuthPolicy, error)
- func (w *Wide) IssueChallenge(ctx context.Context, c Challenge) error
- func (w *Wide) IssueEnrolmentCode(ctx context.Context, c EnrolmentCode) (bool, error)
- func (w *Wide) IssueExchangeCode(ctx context.Context, c ExchangeCode) error
- func (w *Wide) IssueGrant(ctx context.Context, namespace string, task agk.TaskID, id string, ...) (Granted, error)
- func (w *Wide) IssueJoinToken(ctx context.Context, pool string, labels []string, by string, ...) (JoinToken, error)
- func (w *Wide) Join(ctx context.Context, j Joining, rotateAfter time.Duration, now time.Time) (Joined, error)
- func (w *Wide) LiftSuspension(ctx context.Context, login, reason string) (bool, error)
- func (w *Wide) ListWorkflows(ctx context.Context, among []Workflow) ([]ListedWorkflow, error)
- func (w *Wide) Listening(ctx context.Context, published, eventType, source string) ([]Listening, error)
- func (w *Wide) LiveTokens(ctx context.Context, principal string, now time.Time) (int, error)
- func (w *Wide) Locate(ctx context.Context, run agk.RunID) (namespace, workflow string, err error)
- func (w *Wide) LogObjectRecorded(ctx context.Context, l TaskLog, key string) (bool, error)
- func (w *Wide) Logins(ctx context.Context) ([]string, error)
- func (w *Wide) Lose(ctx context.Context, namespace string, key agk.TaskID, row, runner string, ...) (bool, error)
- func (w *Wide) Losses(ctx context.Context, namespace string, run agk.RunID) ([]Loss, error)
- func (w *Wide) Lost(ctx context.Context, now time.Time, batch int) (int, error)
- func (w *Wide) Memo(ctx context.Context, namespace, key string) (Memo, error)
- func (w *Wide) MemoAlive(ctx context.Context, namespace string, m Memo, files []agk.URI) (bool, error)
- func (w *Wide) Memoise(ctx context.Context, namespace string, m Memo) error
- func (w *Wide) MintToken(ctx context.Context, t APIToken) error
- func (w *Wide) NameHolder(ctx context.Context, name string) (*NameHeld, error)
- func (w *Wide) NamespaceAvatar(ctx context.Context, name string) ([]byte, time.Time, error)
- func (w *Wide) NamespaceNamed(ctx context.Context, name string) (Namespace, error)
- func (w *Wide) NamespacePolicy(ctx context.Context, namespace string) (AuthPolicy, error)
- func (w *Wide) Namespaces(ctx context.Context) ([]Namespace, error)
- func (w *Wide) NamespacesOwnedBy(ctx context.Context, principal string) ([]Namespace, error)
- func (w *Wide) NextInLine(ctx context.Context, namespace, group string, run agk.RunID) (bool, error)
- func (w *Wide) NotificationsOf(ctx context.Context, recipient string, now time.Time) ([]Notification, error)
- func (w *Wide) Occupancy(ctx context.Context, now time.Time) ([]Occupancy, error)
- func (w *Wide) OpenSession(ctx context.Context, s Session) error
- func (w *Wide) Ownerless(ctx context.Context) ([]string, error)
- func (w *Wide) PasskeyHandle(ctx context.Context, login string, fresh []byte) ([]byte, error)
- func (w *Wide) PasskeyHandleOf(ctx context.Context, login string) ([]byte, error)
- func (w *Wide) PasskeyUsed(ctx context.Context, id string, count uint32, backedUp bool, at time.Time) error
- func (w *Wide) PoolStatistics(ctx context.Context, b Buckets) ([]PoolSeries, error)
- func (w *Wide) PortStatistics(ctx context.Context, of Workflow, b Buckets) (map[string][]map[string]int64, error)
- func (w *Wide) Present(ctx context.Context, namespace, workflow string) error
- func (w *Wide) PrincipalKind(ctx context.Context, principal string) (string, error)
- func (w *Wide) Progress(ctx context.Context, namespace string, key agk.TaskID, row, runner string, ...) (bool, error)
- func (w *Wide) Published(ctx context.Context, namespace string, keys []agk.TaskID, at time.Time) (int, error)
- func (w *Wide) Reason() Reason
- func (w *Wide) RecordLogObject(ctx context.Context, l TaskLog, key string) error
- func (w *Wide) Redeem(ctx context.Context, clear string, task agk.TaskID, runner string, ...) (Redeemed, error)
- func (w *Wide) Redeemable(ctx context.Context, clear string, task agk.TaskID, runner string, ...) (Redeemed, error)
- func (w *Wide) RedeemedBefore(ctx context.Context, namespace string, key agk.TaskID, row, runner string) (bool, error)
- func (w *Wide) RemoveAvatar(ctx context.Context, login string) (bool, error)
- func (w *Wide) RemoveCredential(ctx context.Context, login, id string) error
- func (w *Wide) RemoveMember(ctx context.Context, group, login string) (bool, error)
- func (w *Wide) RemoveNamespace(ctx context.Context, name string) error
- func (w *Wide) RemoveNamespaceAvatar(ctx context.Context, name string) (bool, error)
- func (w *Wide) RemovePrincipal(ctx context.Context, principal string) error
- func (w *Wide) RemoveServiceAccount(ctx context.Context, namespace, name string) (ServiceAccount, error)
- func (w *Wide) RenameNamespace(ctx context.Context, from, to string) (bool, error)
- func (w *Wide) RequeueOf(ctx context.Context, namespace string, key agk.TaskID, row string) (int, error)
- func (w *Wide) Revocations(ctx context.Context, namespace, workflow string, p access.Principal) ([]Revocation, error)
- func (w *Wide) Revoke(ctx context.Context, runner, by, why string, at time.Time, grace time.Duration) (Runner, error)
- func (w *Wide) RevokeSessions(ctx context.Context, login string, hash []byte, at time.Time) (int, error)
- func (w *Wide) RevokeToken(ctx context.Context, principal, id string, at time.Time) (bool, error)
- func (w *Wide) Rewake(ctx context.Context, namespace string, run agk.RunID, version string, ...) error
- func (w *Wide) Rotate(ctx context.Context, ro Rotating, rotateAfter time.Duration, now time.Time) (Rotated, error)
- func (w *Wide) Run(ctx context.Context, run agk.RunID) (Evaluation, error)
- func (w *Wide) RunDurations(ctx context.Context, among []Workflow, b Buckets, bins int) ([]Bin, error)
- func (w *Wide) RunStatistics(ctx context.Context, among []Workflow, b Buckets) ([]RunBucket, error)
- func (w *Wide) RunnerPoolNamed(ctx context.Context, name string) (RunnerPool, error)
- func (w *Wide) RunnerPools(ctx context.Context) ([]RunnerPool, error)
- func (w *Wide) Runners(ctx context.Context) ([]Runner, error)
- func (w *Wide) Runs(ctx context.Context, among []Workflow, q RunQuery) ([]ListedRun, error)
- func (w *Wide) SaveDecision(ctx context.Context, d Decision) error
- func (w *Wide) ServiceAccount(ctx context.Context, namespace, name string) (ServiceAccount, error)
- func (w *Wide) ServiceAccounts(ctx context.Context, namespace string) ([]ServiceAccount, error)
- func (w *Wide) ServiceAccountsIn(ctx context.Context, namespaces []string) ([]ServiceAccount, error)
- func (w *Wide) SessionByHash(ctx context.Context, hash []byte, now time.Time) (Session, error)
- func (w *Wide) SetAvatar(ctx context.Context, login string, png []byte, at time.Time) error
- func (w *Wide) SetBootstrapToken(ctx context.Context, hash []byte) (bool, error)
- func (w *Wide) SetEmail(ctx context.Context, login, email string) error
- func (w *Wide) SetGroup(ctx context.Context, namespace string, run agk.RunID, group string) error
- func (w *Wide) SetInstallationPolicy(ctx context.Context, p AuthPolicy, at time.Time) error
- func (w *Wide) SetNamespaceAvatar(ctx context.Context, name string, png []byte, at time.Time) error
- func (w *Wide) SetNamespacePolicy(ctx context.Context, namespace string, p AuthPolicy, at time.Time) error
- func (w *Wide) SetOwner(ctx context.Context, name, owner string) error
- func (w *Wide) SetPassword(ctx context.Context, login, id, hash string, at time.Time) (Credential, bool, error)
- func (w *Wide) SetQuotas(ctx context.Context, name string, q Quotas) error
- func (w *Wide) ShipChunk(ctx context.Context, was, now TaskLog, c *LogChunk) error
- func (w *Wide) ShippedChunk(ctx context.Context, l TaskLog, seq int) (LogChunk, bool, error)
- func (w *Wide) ShippingLog(ctx context.Context, clear string, task agk.TaskID, runner string) (TaskLog, error)
- func (w *Wide) ShutEnrolmentCode(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, string, error)
- func (w *Wide) SignedIn(ctx context.Context, login string, at time.Time) error
- func (w *Wide) Slots(ctx context.Context, namespace string, ending ...agk.TaskID) (int, error)
- func (w *Wide) StartTOTP(ctx context.Context, e TOTPEnrolment) error
- func (w *Wide) StepHours(ctx context.Context, of Workflow, from, to time.Time) (map[string][]Percentiles, error)
- func (w *Wide) StepStatistics(ctx context.Context, of Workflow, b Buckets) (map[string][]StepBucket, error)
- func (w *Wide) StopReport(ctx context.Context, namespace string, key agk.TaskID, row, runner string, ...) (bool, error)
- func (w *Wide) StorageOf(ctx context.Context, name string) (string, error)
- func (w *Wide) Suspend(ctx context.Context, login, reason string) (bool, error)
- func (w *Wide) TOTPEnrolmentOf(ctx context.Context, login string, now time.Time) (TOTPEnrolment, error)
- func (w *Wide) TOTPUsed(ctx context.Context, id string, step int64, at time.Time) error
- func (w *Wide) TakeChallenge(ctx context.Context, value []byte, now time.Time) (Challenge, error)
- func (w *Wide) TakeExchangeCode(ctx context.Context, hash []byte, now time.Time) (ExchangeCode, error)
- func (w *Wide) TaskRow(ctx context.Context, namespace string, key agk.TaskID) (string, error)
- func (w *Wide) TellAdministrators(ctx context.Context, login string, at time.Time) ([]string, error)
- func (w *Wide) TellOwners(ctx context.Context, what Widening) ([]string, error)
- func (w *Wide) TellOwnersIn(ctx context.Context, namespace string, what Widening) ([]string, error)
- func (w *Wide) TellPasskeyRefused(ctx context.Context, login, credential string, at time.Time) error
- func (w *Wide) Token(ctx context.Context, id string) (APIToken, error)
- func (w *Wide) TokenByHash(ctx context.Context, hash []byte, now time.Time) (APIToken, error)
- func (w *Wide) TokenUsed(ctx context.Context, id string, at time.Time) error
- func (w *Wide) TokensOf(ctx context.Context, principal string, namespaces []string, now time.Time) ([]APIToken, error)
- func (w *Wide) TouchSession(ctx context.Context, hash []byte, now, until time.Time) error
- func (w *Wide) Trace(ctx context.Context, namespace string, run agk.RunID) (RunTrace, error)
- func (w *Wide) Tree(ctx context.Context, namespace, workflow, commit string) ([]TreeFile, error)
- func (w *Wide) Unarmed(ctx context.Context) ([]Unarmed, error)
- func (w *Wide) Undelivered(ctx context.Context, batch int) ([]Event, error)
- func (w *Wide) Unpublished(ctx context.Context, namespace string, run agk.RunID) ([]agk.TaskID, error)
- func (w *Wide) UpdateProfile(ctx context.Context, login string, p Profile) error
- func (w *Wide) UpdateUser(ctx context.Context, u User) error
- func (w *Wide) UseEnrolmentCode(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, error)
- func (w *Wide) User(ctx context.Context, login string) (User, error)
- func (w *Wide) UserVerificationRequired(ctx context.Context) (bool, error)
- func (w *Wide) Users(ctx context.Context) ([]User, error)
- func (w *Wide) UsersUnderPolicy(ctx context.Context, namespace string, now time.Time) ([]string, error)
- func (w *Wide) VerifyAuditLog(ctx context.Context) error
- func (w *Wide) Version(ctx context.Context, namespace, workflow, commit string) (Version, error)
- func (w *Wide) WakeCaller(ctx context.Context, run agk.RunID, at time.Time) error
- func (w *Wide) Within(ctx context.Context, namespace string, fn func(context.Context, *NS) error) error
- func (w *Wide) Workflows(ctx context.Context, namespace, name string) ([]Workflow, error)
- type Widening
- type Workflow
- type WorkflowRecord
- type Writing
- type Written
Constants ¶
const ( CredentialPasskey = "passkey" CredentialPassword = "password" CredentialTOTP = "totp" )
The types of credential, as credentials.type and $defs/credential write them.
const ( // ImageReferenceMaxBytes is the longest image reference kept, 384 bytes: the 255 characters // clients hold a registry's host and a repository's name to together, a colon, and a tag of at // most 128 characters, both from the OCI distribution specification. ImageReferenceMaxBytes = 384 // ManifestMaxBytes is the largest brick manifest kept, 256 KiB: sixty times the largest of the // standard catalog, so that one with a large parameter schema fits and a row stays a row. ManifestMaxBytes = 256 << 10 )
The bounds and the grammar an image reference is held to here, which migration 0050 holds in SQL.
const ( // NamespacePersonal is the namespace a user is given, named after their login and owned by // them. NamespacePersonal = "personal" NamespaceShared = "shared" )
The kinds of namespace, as namespaces.kind writes them.
const ( CeremonyRegistration = "registration" CeremonyAssertion = "assertion" )
The ceremonies, as webauthn_challenges.ceremony and openapi.json's ceremony write them.
const ( // ContainmentHardened is "the default runtime with user-namespace remapping", which every // installation gets always, and what a pool that says nothing is given. ContainmentHardened = "hardened" // ContainmentSandboxed is gVisor's runsc on a pool of its own. ContainmentSandboxed = "sandboxed" // ContainmentSeparated is a pool on hosts of their own. ContainmentSeparated = "separated" )
Containment is what runs a pool's containers.
const ( KindUser = "user" KindGroup = "group" KindServiceAccount = "service_account" )
The kinds of principal, as principals.kind and $defs/principal write them.
const ( // EnrolmentFirstAdministrator is the first administrator's link, made with the bootstrap // token. EnrolmentFirstAdministrator = "first-administrator" // EnrolmentNewUser is the link a new user is given, and given again while they hold no // credential. EnrolmentNewUser = "enrolment" // EnrolmentRecovery is a recovery code, for a user who lost their passkeys. EnrolmentRecovery = "recovery" )
The kinds of enrolment code, as enrolment_codes.kind writes them.
const ( CodeUsed = "used" CodeReplaced = "replaced" CodeLapsed = "lapsed" CodeEnrolled = "enrolled" CodeBootstrapEnded = "bootstrap_ended" )
Why an enrolment code opens nothing, as ShutEnrolmentCode answers it: the part of openCode it fails, in the order openCode reads them.
const ( // AdminAccessWidened is an administrator having widened access in a namespace: written a // grant there by the installation's power, put somebody in a group holding a role there, or // widened their own access there, giving a role to it or taking a deny from it. Told to the // namespace's owners, with the act and who did it. AdminAccessWidened = "admin_access_widened" // PasskeyCounterRefused is a sign-in refused because a passkey's signature counter did not // move forward, told to the passkey's user. PasskeyCounterRefused = "passkey_counter_refused" // BreakGlassRecovery is a recovery code issued to an administrator by the break-glass path, // agentiik-api recover, told to every administrator, the one recovered included. BreakGlassRecovery = "break_glass_recovery" )
The kinds of notification, as the wire's $defs/notification names them.
const ( // ActGranted is a grant or a deny an administrator wrote by the installation's power, or a // role they gave their own access. ActGranted = "granted" // ActDenyLifted is a deny an administrator revoked from their own access. ActDenyLifted = "deny_lifted" // ActJoinedGroup is a user an administrator put in a group holding a role in the namespace, // themselves or somebody else. ActJoinedGroup = "joined_group" // ActLeftGroup is an administrator taking themselves out of a group whose deny applied in the // namespace. ActLeftGroup = "left_group" // ActGroupRemoved is an administrator removing a group they were in, whose deny applied in the // namespace. ActGroupRemoved = "group_removed" )
The acts an AdminAccessWidened notification tells, as the wire's $defs/notification names them.
const ( // VisibilityAll is a variable every workflow of the namespace reads. VisibilityAll = "all" // VisibilitySelected is a variable the workflows it names read, and no other. VisibilitySelected = "selected" )
The visibilities a variable has, as namespace_variables.visibility and the routes write them.
const ( // VariablesMax is how many variables a namespace may hold. VariablesMax = 1000 // VariablesMaxBytes is what a namespace's values may weigh in all, each written as compact // JSON. VariablesMaxBytes = int(agk.DefaultEnvelopeMaxBytes) // VariablesMaxValues is how many values they may hold in all, each value and everything in // it counted, as a run's inputs are counted. VariablesMaxValues = agk.DefaultMaxItems )
The bounds a namespace's variables are held to, together.
A run keeps the variables it reads, and the controller reads them at every decision it takes on the run, as it reads the run's inputs: so the namespace's variables are held in all to the two bounds a run's inputs are held to, one envelope's weight and as many values as one envelope may carry items, and whatever a run reads of them costs the controller no more than its inputs may. The count bounds a listing, which answers them whole, as the console shows them on one page.
const ( // SourceGit is a commit a git push carried, whose objects are in the repository's packs. SourceGit = "git" // SourceTree is a commit agk push sent as a tree, whose files alone are stored: no clone holds // it unless a git push carried that commit since. SourceTree = "tree" )
The two ways a version arrives, as workflow_versions.source holds them.
const BuiltIn = "agentiik"
BuiltIn is the name of every namespace's built-in identity, and of no other service account.
const ChallengeLife = 5 * time.Minute
ChallengeLife is how long a challenge is taken: five minutes, the time a person takes to find an authenticator and unlock it, and short enough that one copied off a screen is dead by the time anybody could use it. The table holds it too.
const ChallengesLive = 10_000
ChallengesLive is how many challenges may be open at once across the installation. Anybody may start a ceremony, and each keeps a row for five minutes, so without a bound whoever can send requests fills the table as fast as they send them. Ten thousand is far more ceremonies than an installation's people start in five minutes, and a table that small is read and swept in no time. The bound is the installation's alone, with none per address: what it keeps is the table, which a flood from many addresses fills as surely as one from one.
const DefaultGrace = 24 * time.Hour
DefaultGrace is how long an object sits at a count of zero before it may be collected.
const ExchangeCodeLife = time.Minute
ExchangeCodeLife is how long a code is taken: a minute, the time a browser takes to follow a redirect to a port of its own machine, and short enough that one read off a browser's history afterwards opens nothing. The table holds it too.
const HeartbeatInterval = 10 * time.Second
HeartbeatInterval is how often a runner says it is there: "A runner posts one heartbeat every 10 seconds to the API".
A constant, and not something the answer to a heartbeat tells a runner: the wire's answer is closed and carries no interval, and the documentation fixes the figure, so the runner and Lost both count in the one the page gives. A runner judged by another interval than the one it reports at would be declared lost while it reported on time, or kept long after it had gone.
const HoursOfTheWeek = 7 * 24
HoursOfTheWeek is how many cells a heatmap of a week holds, an hour of each of its days.
const LiveChannel = "agentiik_live"
LiveChannel is the channel a run, a step, a task, a notification, a runner or a pool says it changed on.
A payload names what changed and nothing of it, "a notification carries only an identifier", as on the run channel and the log channel: what it names is read through the route that answers it, under that route's permissions. It is a latency optimisation in the same way: a change said while nothing listened is one a console reads when it connects again, since it reads everything it shows then.
const LogChannel = "agentiik_task_log"
LogChannel is the channel a shipment says on that a task's log moved on.
The payload is the idempotency key the log is of, which carries the run and the step a reader follows and nothing else: "a notification carries only an identifier". It is sent in the transaction that records the chunk, and "PostgreSQL delivers such an event only once the transaction commits", so a reader woken by it finds the chunk there. As on the run channel, it is a latency optimisation and not the guarantee: a reader that was not listening when it went out finds the chunk when WatchLogs next sweeps.
const LostAfter = 3 * HeartbeatInterval
LostAfter is how long a task in flight may go unaccounted for before Lost moves it: "Three missed intervals move a task to lost."
const MaxBuckets = 1000
MaxBuckets is the most buckets one series is counted in: more than any chart draws, which a query would pay for all the same.
const MaxRefBytes = 1024
MaxRefBytes is the longest ref name held, 1,024 bytes, a bound git itself does not set: a ref is a key of an index, which PostgreSQL holds to some 2,700 bytes a row, and git keeps a ref it writes as a file under .git, whose path macOS holds to 1,024, so no ref a clone can check out is past it.
const NotificationKept = 90 * 24 * time.Hour
NotificationKept is how long a notification is kept from when it was written: "long enough to reach someone back from leave, and bounded so that GET /api/v1/me does not grow for ever".
const PublishedByTheStep = -1
PublishedByTheStep is the Shard of an envelope the step published.
"A port produces exactly one envelope, once, when the emitting step ends. A step split into shards has its shard envelopes concatenated port by port before publication." The publication is what steps.ports records and what a downstream step reads; a shard's own envelope is working material.
const RepackAbove = 16
RepackAbove is how many live packs a repository holds before the repack writes their objects into one: sixteen, since a fetch looks an object up in every live pack's index, newest first, and every push that sends objects makes a pack of its own. A repository pushed to a few times a day is repacked every week or two, and one that nobody pushes to never.
const RunChannel = "agentiik_run"
RunChannel is the channel the API signals a new run on.
"When the API creates a run it commits the row and issues a NOTIFY carrying the run identifier. PostgreSQL delivers such an event only once the transaction commits, and only to sessions currently listening." One channel for the installation, because the controller that listens is the installation's.
const Silence = 2 * HeartbeatInterval
Silence is the shortest gap between two heartbeats of a runner written down as a silence: two intervals, the first a person reading the chart of the pools would call a gap. See migration 0065.
const SuspendedNoPasskey = "no_passkey"
SuspendedNoPasskey is the reason an account is suspended where passwords were forbidden while it held no passkey the policy accepts, as users.suspended_for writes it.
const TOTPEnrolmentLife = 10 * time.Minute
TOTPEnrolmentLife is how long a TOTP generator waits for the code that confirms it: ten minutes, the time a person takes to find their phone, open an authenticator application and scan, as the table's constraint holds it.
Variables ¶
var ErrBootstrapEnded = errors.New("db: the bootstrap token ended when the first administrator signed in")
ErrBootstrapEnded is the bootstrap token asked for after the first administrator signed in, which ended it for good.
var ErrBuiltIn = errors.New("db: that is a namespace's built-in identity")
ErrBuiltIn is a namespace's built-in identity where a service account somebody created is meant: it is created with its namespace and goes with it, since the runs nobody started there are attributed to it, and removing it would leave them attributed to nobody.
var ErrCalledAlready = errors.New("db: that dispatch has called a run already")
ErrCalledAlready is a call whose dispatch has started a run already: the pass that made it died before writing it down, and the next finds that run rather than starting a second.
var ErrCredentialExists = errors.New("db: that credential is enrolled already")
ErrCredentialExists is a credential ID already enrolled, by anybody, or a second password or TOTP for one user.
var ErrDefaultBranch = errors.New("db: the default branch is not deleted: another branch is named the default first")
ErrDefaultBranch is a push deleting the default branch, which is refused.
var ErrEnrolled = errors.New("db: that user holds a credential already")
ErrEnrolled is a first administrator's link or a new user's link asked for a user who holds a credential already: those links enrol the first passkey of an account that holds none, and a lost one is replaced with a recovery code.
var ErrFenced = errors.New("db: this controller's term has ended and another holds the lock")
ErrFenced is a write by a controller that is no longer the active one.
"Because a partitioned former holder may not yet know it has lost, every controller write carries the lock's acquisition counter as a fencing token and a write bearing an older counter is refused. Election alone would not be safe; the fencing token is what makes it so." A controller seeing this has lost the lock and has not noticed yet, and the right answer is to stop being a controller rather than to retry.
var ErrGone = errors.New("db: that artifact has expired or been collected")
ErrGone is it existed and is finished. An API answers 410 and not 404, "so that a client can tell this existed and is finished from this never existed". Resolve returns what it found alongside this error, because the answer still carries the name, the size and the digest.
var ErrInFlight = errors.New("db: every fetch left of that artifact is being served")
ErrInFlight is a budget whose every fetch left is being served: none is spent yet, since none has completed, and none can be handed to anybody else, since each may. An API answers 409, and a fetch comes back if a transfer holding it does not complete.
var ErrLogExpired = errors.New("db: the logs of that run are past their retention")
ErrLogExpired is a shipment for a run whose retention has run out, whose logs the purge takes or has taken, so that a chunk arriving then would name an object nothing will ever delete.
var ErrNameTaken = errors.New("db: that name is a login or a namespace already")
ErrNameTaken is a login where a namespace of that name exists, or a namespace where a login does: the two share one name space, since a user's personal namespace is named after their login.
var ErrNamespaceRefusesPool = errors.New("db: the task's namespace does not allow that runner's pool")
ErrNamespaceRefusesPool is a redemption of a task by a runner of a pool the task's namespace leaves out of its allowed_runner_pools.
ErrPoolRefusesNamespace from the namespace's side, and answered the same way: a namespace allows or refuses a pool for every runner of it, so no runner of the pool may ever run the task. The controller publishes no task to such a pool, so this is a namespace whose allowed pools changed while the task waited.
var ErrNoAccessGrant = errors.New("db: no access grant of that identifier")
ErrNoAccessGrant is a grant nobody wrote in that namespace, or one already revoked.
var ErrNoArtifact = errors.New("db: no artifact of that name was written on that port")
ErrNoArtifact is nothing of that name was ever written here. An API answers 404.
var ErrNoAvatar = errors.New("db: that user holds no photo")
ErrNoAvatar is a user who holds no photo.
var ErrNoBranch = errors.New("db: the repository holds no such branch")
ErrNoBranch is a default branch named that the repository does not hold, where it holds commits.
var ErrNoChallenge = errors.New("db: no open challenge of that value")
ErrNoChallenge is a challenge that opens nothing: never issued, taken already, or past its minutes.
var ErrNoCredential = errors.New("db: no credential of that identifier")
ErrNoCredential is a credential nobody enrolled, or one of somebody else's.
var ErrNoDeclaration = errors.New("db: the namespace declares no secret of that name")
ErrNoDeclaration is a secret the namespace does not declare.
var ErrNoDispatch = errors.New("db: that task_id is no dispatch of that task")
ErrNoDispatch is a task_id that names no dispatch of the key it came with.
var ErrNoEnrolmentCode = errors.New("db: no open enrolment code of that value")
ErrNoEnrolmentCode is a code that opens nothing: never issued, used, revoked or expired.
var ErrNoEnvelope = errors.New("db: no envelope there")
ErrNoEnvelope is no envelope where one was asked for: a port the step has not published, or one no dispatch of the step was handed, or no dispatch of that attempt and shard.
var ErrNoExchangeCode = errors.New("db: no open exchange code of that value")
ErrNoExchangeCode is a code that opens nothing: never minted, taken already, or past its minute.
var ErrNoGrant = errors.New("db: no grant of that value for that task")
ErrNoGrant is nothing of that value, for that task, that has not expired. One error for all three, because telling a caller which of them it was is telling somebody guessing whether they had the right task, the right value, or merely the wrong moment.
var ErrNoHook = errors.New("db: no webhook of the namespace answers that path and method")
ErrNoHook is a path and a method no webhook of the namespace answers, which a request is answered as an absent one is.
var ErrNoHookCredential = errors.New("db: no credential was written for the webhook")
ErrNoHookCredential is a webhook no credential was written for.
var ErrNoJoinToken = errors.New("db: that join token cannot be redeemed")
ErrNoJoinToken is a join token that is wrong, spent or expired.
var ErrNoLog = errors.New("db: nothing has shipped a log for that task")
ErrNoLog is a dispatch nothing has shipped a log for.
var ErrNoManifest = errors.New("db: the repository holds no brick manifest for that image")
ErrNoManifest is an image the repository holds no brick manifest for.
var ErrNoMemo = errors.New("db: no cache entry under that key")
ErrNoMemo is a key no cache entry is held under.
var ErrNoNamespace = errors.New("db: no namespace of that name")
ErrNoNamespace is a declaration written into a namespace nobody created.
var ErrNoNamespaceAvatar = errors.New("db: that namespace has no picture")
ErrNoNamespaceAvatar is a namespace that has no picture.
var ErrNoNotification = errors.New("db: no notification of that identifier for that principal")
ErrNoNotification is no notification of that identifier kept for that principal: dismissed already, past its 90 days, or never theirs.
var ErrNoOutput = errors.New("db: the run records no output of that name")
ErrNoOutput is no output of that name recorded on the run: the workflow declares none, or the run has not ended, or it ended without every output it declares, since a run's outputs are written when it ends and only when all of them are there.
var ErrNoPack = errors.New("db: that pack is not receiving")
ErrNoPack is a pack no longer receiving: collected once it had been receiving past the grace, or never recorded.
var ErrNoPassword = errors.New("db: a TOTP generator is enrolled beside a password, and that user holds none")
ErrNoPassword is a TOTP generator enrolled for a user holding no password: "TOTP exists only alongside a password".
var ErrNoPin = errors.New("db: the repository holds no digest for that image tag")
ErrNoPin is an image tag the repository holds no digest for.
var ErrNoPrincipal = errors.New("db: no principal of that name")
ErrNoPrincipal is a principal nobody created.
var ErrNoRun = errors.New("db: no run of that identifier")
ErrNoRun is nothing of that identifier in that namespace.
var ErrNoRunner = errors.New("db: no runner of that identifier")
ErrNoRunner is nothing of that identifier, or nothing that credential opens. One error for both, for the reason ErrNoGrant is one error for three.
var ErrNoRunnerPool = errors.New("db: no runner pool of that name")
ErrNoRunnerPool is a pool nobody created.
var ErrNoSession = errors.New("db: no live session of that identifier")
ErrNoSession is a session that opens nothing: never opened, revoked, or idle past its expiry.
var ErrNoStep = errors.New("db: the run has no step of that name")
ErrNoStep is a run with no step of that name.
var ErrNoTOTPEnrolment = errors.New("db: no TOTP generator is waiting for its first code")
ErrNoTOTPEnrolment is a TOTP generator nobody started, or one whose minutes are up.
var ErrNoToken = errors.New("db: no live token of that value")
ErrNoToken is a token that opens nothing: never minted, revoked or expired.
var ErrNoTree = errors.New("db: that version was recorded without its tree")
ErrNoTree is a version recorded without its tree.
Separate from ErrNoVersion because the version is real and runs can be decided from it: what is missing is the directory a container is given, and answering that with an empty one would start a step on something that looks like a repository and is not one.
var ErrNoValue = errors.New("db: the built-in store holds no value of that name")
ErrNoValue is a secret the built-in store holds no value for: never written, or forgotten.
var ErrNoVariable = errors.New("db: the namespace holds no variable of that name")
ErrNoVariable is a variable the namespace does not hold.
var ErrNoVersion = errors.New("db: no version of that workflow at that commit")
ErrNoVersion is nothing of that commit.
var ErrNoWorkflow = errors.New("db: no workflow of that name in that namespace")
ErrNoWorkflow is a grant on a workflow its namespace does not hold.
var ErrNotCalled = errors.New("db: that dispatch has called no run")
ErrNotCalled is a dispatch that has started no run.
var ErrNotHeld = errors.New("db: that dispatch was never bound to that runner")
ErrNotHeld is a loss or a progress message naming a dispatch that was never bound to the runner it names.
var ErrNotItsKey = errors.New("db: that signature is not by the key the runner joined with")
ErrNotItsKey is a rotation whose signature is not by the key its runner joined with.
var ErrNotThePoolsLabel = errors.New("db: a join token permits only labels its pool carries")
ErrNotThePoolsLabel is a join token asked to permit a label its pool does not carry.
var ErrNotYetDispatched = errors.New("db: that dispatch is not recorded as dispatched yet")
ErrNotYetDispatched is progress on a dispatch its runner holds and the controller has not yet recorded as dispatched, which a later delivery will find recorded.
var ErrOtherTree = errors.New("db: that commit is already recorded with another tree")
ErrOtherTree is a commit already recorded with a different tree.
"A version is a commit", and a commit names exactly one tree, so the same commit arriving with other files is a rewritten history or a push that says it is something it is not. Neither is a reason to change what a run pinned to that commit is already using.
var ErrOwnsNamespace = errors.New("db: that principal owns a namespace")
ErrOwnsNamespace is a principal refused removal while it owns a namespace, which would be left owned by somebody who is gone.
var ErrPackCollected = errors.New("db: that pack is being collected")
ErrPackCollected is a pack a push sends again, by the checksum that names it, while the collection deletes its files: the push is refused, and sent again once the files are gone.
var ErrPersonalRename = errors.New("db: a personal namespace is named after its user's login and never renamed")
ErrPersonalRename is a user's personal namespace asked to be renamed: it is named after its user's login, which never changes.
var ErrPoolRefusesNamespace = errors.New("db: that runner's pool does not accept the task's namespace")
ErrPoolRefusesNamespace is a redemption of a task whose namespace the redeeming runner's pool does not accept.
No runner of that pool may ever run it, since what a pool accepts is the pool's and every one of its runners carries it, so it is not put back for the next one: the redemption can never be answered, and the runner reports that no container ran. The controller refuses to publish such a task in the first place, so this is a pool whose policy changed while the task waited, or a grant presented by a runner of a pool that does not run the namespace. It is the runner's pool that is read and not the one the task was published to, which neither the task nor its grant records.
var ErrPrincipalExists = errors.New("db: a principal of that name exists")
ErrPrincipalExists is a principal created under a name another already has.
var ErrProtected = errors.New("db: a ref was protected while the push was judged")
ErrProtected is a ref a push was judged to move as unprotected, and that was protected before its refs moved.
var ErrRotationReplayed = errors.New("db: a rotation signs a later time than the last one did")
ErrRotationReplayed is a rotation signing a request time no later than the last one its runner rotated with.
var ErrRunnerNarrowed = errors.New("db: that runner narrows itself to namespaces that leave out the task's")
ErrRunnerNarrowed is a redemption of a task whose namespace the redeeming runner's own narrowing, AGK_RUNNER_NAMESPACES, leaves out.
Separate from ErrPoolRefusesNamespace because the runner does the opposite with the message: the pool accepts the namespace, so another runner of the pool may take the task, and it is put back rather than reported. The runner checks its narrowing before it redeems; this is the API holding it to the same list, sent at join, rather than trusting it to.
var ErrRunnerNotTaking = errors.New("db: that runner is draining or revoked, and takes no new task")
ErrRunnerNotTaking is a redemption by a runner that is draining or revoked of a task it does not hold yet, since neither takes anything new.
Separate from ErrTaskHeld because the runner does the opposite with the message: the task is nobody's yet and some other runner of the pool should have it, so it is put back rather than acknowledged.
var ErrRunnerPoolExists = errors.New("db: a runner pool of that name exists")
ErrRunnerPoolExists is a pool created under a name another pool already has.
var ErrRunnerRevoked = errors.New("db: that runner is revoked")
ErrRunnerRevoked is a drain ordered for a revoked runner, which would only undo part of the revocation, or a rotation by one still in its grace, which would carry the runner past it.
var ErrRunsGoing = errors.New("db: a run of the workflow has not finished")
ErrRunsGoing is a workflow a run of which has not finished, queued, running or waiting, which a move refuses: the document such a run is decided from names the namespace it started in.
var ErrScheduleMoved = errors.New("db: the schedule moved on since it was read")
ErrScheduleMoved is a schedule that is no longer where its firing found it: another firing moved it on, or a push armed it anew. The firing does nothing, and the next pass reads the row again.
var ErrSessionRefused = errors.New("db: nothing opens that session")
ErrSessionRefused is a session nothing may open: one a credential opens for a suspended user.
var ErrSignCountBehind = errors.New("db: that passkey's signature counter did not move forward")
ErrSignCountBehind is an assertion whose signature counter did not move past the one recorded, which is what a cloned authenticator's does. Two authenticators that count nothing both report zero, and are not refused for it.
var ErrStale = errors.New("db: the run has been decided since this copy of it was read")
ErrStale is a decision written against a run that has moved on.
"Seq counts the decisions taken against this state. It is what a caller persisting the state writes beside it to tell a stale copy from a current one, and what makes two writers of one run detectable rather than silent." A controller seeing this read the run, decided, and found the row changed underneath: the decision it took was taken against a state that no longer exists, and the answer is to read again and decide again rather than to force it.
var ErrStaleRef = errors.New("db: a ref is no longer where the push found it")
ErrStaleRef is a ref no longer where the push found it: another push moved it first.
var ErrTOTPSpent = errors.New("db: a code of that step, or of a later one, was accepted already")
ErrTOTPSpent is a TOTP code of a step at or before the one a code was last accepted at: accepted once already, or older than one that was.
var ErrTaskHeld = errors.New("db: that task is held by another runner")
ErrTaskHeld is a task another runner is already working on.
Separate from ErrNoGrant because the caller is an authenticated runner rather than somebody guessing: it presented a valid grant for a real task, and what it needs to know is that the work is somebody else's, or over, and that it acknowledges the message and starts nothing rather than retrying or putting the message back for the next runner to be refused in its turn.
var ErrWorkflowExists = errors.New("db: the namespace holds a workflow of that name")
ErrWorkflowExists is a workflow created under a name its namespace holds already.
var ErrWorkflowMoving = errors.New("db: the workflow is being moved to another namespace")
ErrWorkflowMoving is a workflow frozen by a move asked and not yet carried out: nothing that writes it is let in until it is done, a push, a run, a replay, a rename or a deletion.
var ErrWorkflowPurging = errors.New("db: a workflow deleted under that name is still being purged")
ErrWorkflowPurging is a workflow created under the name of one deleted whose purge has not ended: the name is free once the purge has removed the workflow's row, and not before.
var Keepalives = []struct{ Name, Value string }{
{"tcp_keepalives_idle", "10"},
{"tcp_keepalives_interval", "5"},
{"tcp_keepalives_count", "3"},
}
Keepalives are the settings every connection of the API and the controller asks its server for, as run-time parameters of the session, unless the URL sets them itself.
Two things are held by a session and released only when PostgreSQL notices it is gone: the controller's advisory lock, and the head of the audit log's chain, which an act locks from its append until it commits. A program that died or was cut off without a reset leaves nothing on the wire to notice, and the server's own default is the operating system's, which on Linux probes an idle connection after two hours. For all that time no standby could take over, and every audited act of the installation, a runner's revocation among them, would wait behind the one whose commit never came. With these the server probes a silent session after ten seconds and drops it after three unanswered probes five seconds apart, so both are released within half a minute.
Functions ¶
func CanonicalImage ¶ added in v0.4.0
CanonicalImage is an image named by a digest as the store keys it: its repository and its digest, less any tag written beside the digest, since the digest is what is pulled and alpine:3.21@sha256: and alpine@sha256: of one digest are one image. An image named otherwise is answered as it is.
func CheckRef ¶ added in v0.4.0
CheckRef refuses a ref a repository cannot hold: anything but a branch or a tag, a name git refuses, and a name past MaxRefBytes, as the table refuses it, so that a push is refused before anything is written rather than by the table in the middle of it.
func Connect ¶
Connect opens one connection, held to the TLS floor as a pool is, for the one caller that needs a connection and not a pool: migrating, which runs as the role that may change the schema.
func Migrate ¶
Migrate applies what has not been applied, in order, and answers with what it did.
Each migration runs in a transaction of its own and is recorded in the same one, so a migration that fails leaves the schema exactly as it was and the record agrees: an installation is upgraded rather than rebuilt, which is what this exists for.
It takes a connection rather than a Pool because it is the one thing that legitimately runs as a role that may create tables, and that role is not the one the application connects as. Open would refuse it. An installation calls Provision, which calls this and then creates the role the application does connect as. Two calls at once race on the catalogue, so Provision holds a lock around this one.
func MigrateThrough ¶ added in v0.3.0
MigrateThrough is Migrate, stopping after the migration named last, or applying every one where last is empty.
An installation never stops part way, and nothing but a test calls it with a name: a test of an upgrade migrates a database as far as the release it upgrades from had, fills it as that release did, and then lets Provision apply the rest, as the next release's init does. Exported for the tests that upgrade through the programs rather than through this package, since an upgrade is only proved where the programs that read the database afterwards are the ones that ship.
func Provision ¶
Provision applies the migrations as the privileged connection it is given, then creates the role the API and the controller connect as, or brings an existing one back to that shape, and answers with the migrations it applied.
The role is LOGIN NOSUPERUSER NOBYPASSRLS, and creates no database, no role and no replication slot. It may connect to this database, use the schema, read and write every table the migrations created but the audit log's, which it may only append to and read, as appendOnly says, and read schema_migrations, which a binary reads to refuse to start against a database ahead of it, and which a role that could write to would have the next upgrade apply a migration again or skip one. Before any of that is granted, in the same transaction, the role is taken out of every role it is a member of and loses what it holds on the database, on a parameter, on the schema and on every relation in it, so it ends with exactly these whatever it held there before: a role somebody widened by hand is narrowed back, and a second call changes nothing. What it may hold elsewhere, in another schema or another database, is not this installation's to reset.
A role that owns the database or anything in it is refused before anything is applied, and the refusal names what it owns. No revoke reaches an owner: the owner of a table may switch off its row level security, and the owner of the database owns schema public and may drop schema_migrations there.
A password is set as a SCRAM verifier computed here, so the password itself never reaches the server. Written into CREATE ROLE, it is statement text, and PostgreSQL logs statement text whenever log_statement covers DDL and whenever a statement fails, which it does by default; createuser and psql's \password send a verifier for the same reason. It is valid until it is replaced, since an expiry the role held before would lock the application out at a moment nobody chose, with a password that is right. An empty password leaves the role's as it was, and a role created without one authenticates some other way, such as the client certificate the Channels table allows: an address that carries no password, because pgx reads it from a password file, must not be what removes it.
The connection needs no superuser, only the right to create roles and to own the schema, which is what a managed PostgreSQL gives its administrator. It refuses the role the connection itself is, before anything is applied, since a role made NOSUPERUSER by its own migration is an installation nobody can migrate again. Two provisionings of one database at once take turns.
func WithKeepalives ¶
WithKeepalives adds the keepalives to a PostgreSQL URL that does not already set them.
Added to the text rather than through net/url, which drops a parameter holding a ; without a word and would lose a setting the operator wrote. pgx takes a parameter it has no use for as a run-time parameter of the session, which is how these reach the server.
Types ¶
type APIToken ¶ added in v0.3.0
type APIToken struct {
ID string
Hash []byte
Principal string
// Permissions and Within narrow the token, and nil does not narrow it that way.
Permissions []string
Within []string
DeviceLabel string
CreatedAt time.Time
ExpiresAt time.Time
LastUsedAt time.Time
RevokedAt time.Time
}
APIToken is a bearer credential of a user or a service account, without its value.
type Activity ¶ added in v0.6.0
type Activity struct {
// At is when it was read, the database's clock.
At time.Time
// Runs are the runs not ended, by state: queued, running and waiting.
Runs map[string]int
// TasksInFlight are the tasks handed to the bus and not yet ended.
TasksInFlight int
// Slots is what the ready runners offer together, and RunnersReady how many they are: ready,
// reporting themselves ready and heard from within LostAfter, which is what runner_capacity
// counts as capacity. Runners is the runners not revoked, ready or not.
Slots int64
RunnersReady, Runners int
}
Activity is what the installation is doing as it is read.
type ActivityBucket ¶ added in v0.6.0
type ActivityBucket struct {
// Runs are the runs created in the bucket, in every namespace, by state, as RunBucket's are:
// an ended run under its final state, one still going under where it is now.
Runs map[string]int
// TasksInFlightMax is the most tasks on their way to a runner or at one and not yet ended at
// once in the bucket, every namespace together, as QuotaBucket's is for one.
TasksInFlightMax int
}
ActivityBucket is what every namespace together did in one bucket, in counts that name no run, workflow or namespace.
type Administrator ¶ added in v0.3.0
Administrator is one of the installation's administrators, and whether they can sign in: not suspended, and holding a credential.
type Armed ¶ added in v0.5.0
type Armed struct {
Entry
Workflow string
Commit string
ArmedBy string
ArmedAt time.Time
// FiredAt is when it last fired, FiredFor the occurrence it fired for, a schedule's, and
// FiredRun the run it started; Skipped says why it started none, where the namespace's
// max_runs_per_hour was spent.
FiredAt time.Time
FiredFor time.Time
FiredRun agk.RunID
Skipped string
// Failures counts a webhook's signature failures, the last at FailedAt.
Failures int64
FailedAt time.Time
}
Armed is one trigger armed, and what has become of it.
type ArtifactSummary ¶ added in v0.6.0
type ArtifactSummary struct {
URI agk.URI `json:"uri"`
Step agk.Step `json:"step"`
Port agk.Port `json:"port"`
Name string `json:"name"`
MediaType string `json:"media_type"`
Size int64 `json:"size"`
// SHA256 is the sixty-four hexadecimal characters the envelope's file carries.
SHA256 string `json:"sha256"`
// Status is live while the artifact may be fetched, expired once its duration ran out, and
// collected once its fetches were spent; RetiredAt is when it stopped being live.
// ExpiresAt is left out where nothing bounds it, a file kept for ever.
Status string `json:"status"`
ExpiresAt time.Time `json:"expires_at,omitzero"`
RetiredAt time.Time `json:"retired_at,omitzero"`
// FetchesLeft is what remains of a fetch budget, which only a workflow output may declare,
// and nil where there is none.
FetchesLeft *int `json:"fetches_left,omitempty"`
}
ArtifactSummary is one file a step published on a port, as its reference holds it: what the envelope's file names, and where it stands in its retention, which the bytes behind it may have outlived or not.
type Attribution ¶ added in v0.3.0
type Attribution struct {
// Principal is the principal with the groups it is in now. A service account belongs to
// none, since a group's members are logins.
Principal access.Principal
// Kind is KindUser or KindServiceAccount, and empty where no principal of that name exists:
// one removed since, with everything it held.
Kind string
// Suspended is a user who holds nothing, whatever their grants, since "a suspended account
// opens no session".
Suspended bool
// Grants are every grant of the namespace naming Principal or one of its groups, on the
// namespace or on the workflow asked about, expired or not, in the order they were written.
Grants []access.Grant
}
Attribution is the principal a run is attributed to, as it stands now in the namespace the run is of: who it is, whether it is still there to hold anything, and the grants of the namespace written for it or for one of its groups, the expired ones among them.
It is what the controller asks package access about before it lets a run in, since "authorisation is re-evaluated when a run is created", and what it names when the answer is no: the expired grants are read because the one that gave the permission is the one whose expiry is the reason.
type AuditQuery ¶ added in v0.6.0
type AuditQuery struct {
// Before is the seq the page ends after: the entries before it.
Before int64
// Limit is the most entries the page holds.
Limit int
// Actor, Action and Target are matched exactly.
Actor, Action, Target string
// Namespace is matched exactly, and Installation keeps the acts on the installation alone,
// which name no namespace.
Namespace string
Installation bool
// Since and Until bound the moment an entry was appended, both included.
Since, Until time.Time
}
AuditQuery is what a page of the audit log is narrowed to, as GET /api/v1/auth/audit asks for one. Each field left at its zero value narrows nothing.
type AuditRecordDisagrees ¶
AuditRecordDisagrees is a chain that holds from its first entry while the entry the last verification recorded reaching does not agree with the record: it has another hash, or the log no longer reaches it.
Only the record shows it, and the record alone cannot tell which it is. Either the chain was written again from that entry or before it, head and all, which is what the record is there to catch, or the record was written by something other than a verification, which the application's role can do. Both want the log compared with its copy outside the installation.
func (*AuditRecordDisagrees) Error ¶
func (d *AuditRecordDisagrees) Error() string
type AuditTrail ¶
type AuditTrail struct {
// contains filtered or unexported fields
}
AuditTrail is the audit log as the export reads it, across the installation.
func (AuditTrail) Exported ¶
Exported is the last entry the sink accepted, and its hash: 0 and audit.Genesis before any.
func (AuditTrail) MarkExported ¶
MarkExported records that the sink accepted every entry up to seq, whose hash is hash. It only moves forward: a controller that lost the lead in the middle of a batch and marks it after the next leader went further leaves the cursor where the further one put it.
func (AuditTrail) Verify ¶
func (a AuditTrail) Verify(ctx context.Context, batch int) (AuditVerification, error)
Verify checks the chain in the database from the last entry a verification reached, up to the head as it stands when it begins, and answers the first *audit.Break. It records how far the chain holds after each batch of at most batch entries, auditBatch where batch is not positive, so that the next verification, by this controller or the one after a failover, carries on from there, and one cut short keeps what it read.
The record is the application's to write, and moves only forward, so it is never taken on trust: the entry it names has to carry the hash recorded beside it, and fields that give that hash, before the chain is carried on from it. Where it does not, the whole log is verified again and the first break found is answered, leaving the record where it was; a chain that holds from its first entry all the same is an *AuditRecordDisagrees, and the record is moved forward to the head it verified, where that is forward.
No entry before the record is read again, which is what bounds the cost on a long log: one changed, hashed again or removed there, while the entry the record names is left as it was, is found by comparing with the copy outside the installation, not here.
type AuditVerification ¶
AuditVerification is how far one verification of the chain in the database went: it carried on after entry From, 0 where it read the log from its first, and found the chain holding through entry Through.
type AuthPolicy ¶ added in v0.3.0
type AuthPolicy struct {
Password string
Passkey string
UserVerification string
DeviceBoundOnly *bool
MinPasskeys int
}
AuthPolicy is how people prove who they are, as $defs/authPolicy writes it. The installation's sets every field. A namespace's sets only what it tightens: an empty string, a nil DeviceBoundOnly and a zero MinPasskeys are the installation's value. Whether a namespace's is tighter needs both, and is the API's to say.
type Beaten ¶
type Beaten struct {
Runner Runner
// Cancel is each key the heartbeat named whose dispatch, bound to this runner, the
// controller has ended as cancelled or timed_out, in the order keys sort in. Never nil, so
// that the answer is always a list.
Cancel []agk.TaskID
}
Beaten is what a heartbeat is answered from: the runner as it now stands, and the keys it is to stop.
type Beating ¶
type Beating struct {
AgentVersion string
// State is ready, draining or unhealthy, the runner's own word on what it will do with new
// work. It is recorded and never obeyed: the installation's word is Runner.State.
State string
Concurrency int64
// Holding is every key in flight on the host.
Holding []agk.TaskID
}
Beating is what a runner says of itself at every heartbeat, as the wire's request has it: which agent it runs, what it will do with new work, how many tasks it will run at once, and the keys it is holding.
type Bin ¶ added in v0.6.0
Bin is one bin of a histogram of durations: the runs whose duration, in milliseconds, is at least From and below Until, or at most Until for the last bin.
type Bootstrap ¶ added in v0.3.0
Bootstrap is the bootstrap token's state: the SHA-256 of the token while it works, and when the first administrator's enrolment or sign-in ended it.
type BrickManifest ¶ added in v0.4.0
BrickManifest is the brick manifest of one image of a repository, by digest: the SHA-256 of the file the image holds at /agk/brick.yaml, which is kept byte for byte and read by Manifest alone, so that a listing costs what it lists and not what every manifest weighs.
type Buckets ¶ added in v0.6.0
Buckets are the buckets a series is counted in: Count of them, each Width long, the first starting at First. The API lays them on whole minutes, quarters, hours or days; this package counts in whatever it is given.
type Called ¶ added in v0.5.0
type Called struct {
Namespace string
Run agk.RunID
Workflow string
Commit string
State agk.RunState
Reason string
}
Called is a run a call started, as the step that made the call reads it.
type Caller ¶ added in v0.5.0
type Caller struct {
Run agk.RunID `json:"run"`
Step agk.Step `json:"step"`
Task agk.TaskID `json:"-"`
}
Caller is the step of another run whose call started a run: "a from naming its caller", and the dispatch that made the call.
type Ceilings ¶
Ceilings are cpu, memory and pids, written as a step writes them: cpu a decimal number of cores, "0.5", memory a whole number with a binary suffix, "8Gi". Each is no ceiling of its kind where it is empty or zero, which is the ordinary case for a pool of uniform hosts where the host itself is the limit.
type Challenge ¶ added in v0.3.0
type Challenge struct {
Value []byte
Ceremony string
// Login is the user a registration enrols, and empty for an assertion, which names nobody
// until the passkey does.
Login string
// EnrolmentCode is the SHA-256 of the code that let a registration start where no session
// did, which the verification spends; nil for one a session started, and for an assertion.
EnrolmentCode []byte
IssuedAt time.Time
ExpiresAt time.Time
}
Challenge is a challenge the options issued, and what it was issued for.
type Change ¶ added in v0.4.0
Change is what a request asking a move changes besides, made first in the move's transaction and in the workflow's namespace, so that a move refused changes nothing: "each field is under its own permission, and a request naming several changes nothing unless every one of them is held". It answers the name the workflow has once it is made, which is the name the move holds in the target, and the audit records it makes, which are appended last.
type ChangeKind ¶ added in v0.6.0
type ChangeKind string
ChangeKind is what kind of thing a LiveChange says changed.
const ( // ChangedRun is a run created or moved on, or one of its steps or tasks: Namespace, Workflow // and Run name it. ChangedRun ChangeKind = "run" // ChangedNotifications is a notification told to Recipient, or dismissed. ChangedNotifications ChangeKind = "notifications" // ChangedRunners is a runner or a pool changed, a heartbeat included. ChangedRunners ChangeKind = "runners" // ChangedAll is everything, said where a change may have been missed: when WatchLive starts // listening, since what changed before was said to nobody, and for a payload it cannot read. ChangedAll ChangeKind = "all" )
type ChangeRefused ¶ added in v0.4.0
type ChangeRefused struct{ Err error }
ChangeRefused is what a Change was refused for, told apart from what the move is refused for, since both can be a name taken: the change's in the namespace the workflow is in, the move's in the target.
func (*ChangeRefused) Error ¶ added in v0.4.0
func (e *ChangeRefused) Error() string
func (*ChangeRefused) Unwrap ¶ added in v0.4.0
func (e *ChangeRefused) Unwrap() error
type Consumption ¶ added in v0.3.0
type Consumption struct {
Namespace string
// Tasks is what max_concurrent_tasks counts, as Slots counts it: tasks handed out, or on
// their way to a runner, and not yet over.
Tasks int64
// RunsLastHour is what max_runs_per_hour counts: the runs created in the last 60 minutes.
RunsLastHour int64
// ArtifactBytes is what max_artifact_bytes counts, as MakeRoom counts it: the bytes of its
// live artifacts, each digest once, and of the uploads not yet referenced.
ArtifactBytes int64
// The quotas, zero where the namespace sets none. max_concurrent_tasks always holds one.
MaxConcurrentTasks int64
MaxRunsPerHour int64
MaxArtifactBytes int64
}
Consumption is one namespace as the quota metrics read it: what it holds against each quota that counts something, and the quota where it sets one.
type Containment ¶
Containment is what a host reported at join of how it contains a container: the runtime its daemon creates them with, and whether that daemon remaps container root to an unprivileged account.
type Credential ¶ added in v0.3.0
type Credential struct {
ID string
Login string
Type string
Label string
CreatedAt time.Time
LastUsedAt time.Time
// A passkey: the COSE public key as the authenticator sent it, the signature counter, the
// AAGUID as received, and the Backup Eligibility and Backup State flags.
PublicKey []byte
SignCount uint32
AAGUID []byte
BackupEligible bool
BackupState bool
// A password: its hash, in the self-describing form its hasher writes.
PasswordHash string
// A TOTP: its secret, sealed under the master key, and the time step its code was last
// accepted at, zero where none was, which is before every step a clock reads since 1970.
TOTPSealed []byte
TOTPStep int64
}
Credential is one credential of one user. The fields of its type are set and the others are empty.
type Decision ¶
type Decision struct {
Namespace string
Run agk.RunID
// Was is the Seq the document was read at, and Seq is what it has become. The write is
// refused if the row is no longer at Was.
Was int
Seq int
Document json.RawMessage
State agk.RunState
StartedAt time.Time
FinishedAt time.Time
// WakeAt is when the run is next due: Plan.Wake for a pass, and the moment of the result
// for a decision recording one, which the pass after it is due at. The zero time is
// "nothing waits on the clock".
WakeAt time.Time
// Retain is the workflow's defaults.retain, how long its envelopes and logs are kept once
// it has finished, and zero where it declares none. "Envelopes and logs are not declared one
// at a time the way an output is, so they live by the workflow's defaults.retain, resolved to
// one date when the run finishes": SaveDecision resolves it, capped by the namespace's
// max_retention_days, which also bounds a workflow that declares none where the namespace sets
// it; neither, and they are kept for ever.
Retain time.Duration
// Outputs are the run's declared outputs as digests, written when it succeeds.
Outputs map[string]any
// Reason is why the run ended as it did, written with the decision that ends it where nothing
// in its workflow is what ended it: a run its principal may no longer start, refused at
// creation. Empty writes none and keeps what the row holds.
Reason string
Steps []StepRow
Tasks []TaskRow
// Envelopes are every envelope this decision's document references, published or per
// shard. They are counted rather than merely written down, so that the collector can
// see the objects the controller put in the store.
Envelopes []EnvelopeRef
// Artifacts are the files those envelopes reference, each with the retention the
// workflow declared for the port that published it. Writing one twice is what a pass
// that decided something else does, and is free: a reference that says the same thing
// is the same reference.
Artifacts []Reference
}
Decision is one pass of the evaluator, written down.
Everything in it lands in one transaction or none of it does. A document saved without its task rows would be a controller that had decided to start work nothing recorded, and rows written without their document would be work recorded against a state that never asked for it.
type Declaration ¶
type Declaration struct {
Name string
Provider string
// Path is where the value sits inside its store, and empty for the built-in one, which
// keeps a value under the namespace and the name it is declared by.
Path string
DeclaredBy string
DeclaredAt time.Time
}
Declaration is one secret of one namespace: the store its value is read from, and where in it.
type DeletedPurge ¶ added in v0.4.0
DeletedPurge is what one call of PurgeDeleted removed: runs, versions, packs handed to the collection, and workflows gone whole, whose names are free from then on.
type Dispatch ¶
type Dispatch struct {
// Row is the task_id, and Task the key it is a dispatch of, which carries the attempt and the
// shard. Requeue counts the times the attempt was handed out again after a loss, 0 for the
// first, so that two dispatches of one key are told apart by a number and not only by an
// identifier.
Row string
Task agk.TaskID
Attempt int
Shard *agk.Shard
Requeue int
State agk.TaskState
// Bound is a dispatch a redemption bound to a runner, which is the only kind that ships a log.
Bound bool
// FinishedAt is when the dispatch ended, and zero while it has not or where nothing said.
FinishedAt time.Time
// Lines, Truncated and FinalSeq are where its log stands, all zero while nothing has shipped.
Lines int
Truncated bool
FinalSeq int
}
Dispatch is one task row of a step and where its log stands.
type Due ¶ added in v0.5.0
type Due struct {
Namespace, Workflow string
Position int
Commit string
Declared json.RawMessage
// DueAt is the occurrence it is due for, and FireAt when it fires, its jitter drawn.
DueAt, FireAt time.Time
}
Due is a schedule whose occurrence is due to fire.
type EnrolmentCode ¶ added in v0.3.0
type EnrolmentCode struct {
Hash []byte
Login string
Kind string
IssuedBy string
IssuedAt time.Time
ExpiresAt time.Time
UsedAt time.Time
}
EnrolmentCode lets one user enrol a passkey, once, within the hour.
type Entry ¶ added in v0.5.0
type Entry struct {
// Kind is schedule, webhook or event, and Position the entry's place in its list under on.
Kind agk.TriggerKind
Position int
// Declared is the entry with the values in force, as JSON: what a listing answers and what
// tells a push declaring it again from one that changed it.
Declared json.RawMessage
// Path and Method are a webhook's, which one trigger of the namespace answers.
Path, Method string
// Type and Source are an event's, where a publication looks for a subscription, and Hears the
// namespace whose events it hears, its own where the file names none.
Type, Source, Hears string
// DueAt and FireAt are a schedule's next occurrence and when it fires, its jitter drawn: what
// it is armed with where the push arms it afresh. An entry declared again keeps the row's.
DueAt, FireAt time.Time
}
Entry is one entry of a version's on block, as it is armed.
type Envelope ¶
type Envelope struct {
Digest string `json:"digest"`
Size int64 `json:"size"`
Items int `json:"items"`
// PurgedAt is when the bytes behind the digest were purged, and the zero time while
// they are still there. The digest outlives them: it is the record of what was
// published.
PurgedAt time.Time `json:"purged_at,omitzero"`
}
Envelope is one published envelope: what the database keeps of it, which is its digest, its size and how many items it carried.
It is what GET /api/v1/runs/{id} answers for each port of a step, so it is spelled as every other field of that answer is, and says nothing of a purge that has not happened.
type EnvelopeRef ¶
type EnvelopeRef struct {
Step agk.Step
// Shard is the position in the step's slice, and PublishedByTheStep for the envelope
// the step published rather than one a shard produced.
Shard int
Port agk.Port
Digest string
Size int64
Items int
}
EnvelopeRef is one envelope a run's decision references, as the database holds it.
Every envelope the document names is counted here, not only the ones a step published. A shard's envelope is in the document until the step publishes, so a run resumed inside that window needs its bytes, and an object with no row at all is an object the collector cannot see and therefore never deletes. Counting all of them is what makes the store's contents accounted for rather than merely mostly accounted for.
type Evaluation ¶
type Evaluation struct {
Namespace string
// Storage is the namespace's storage name, which every object of it is kept under, its
// envelopes among them (NS.Storage).
Storage string
Run agk.RunID
Workflow string
Commit string
State agk.RunState
// Document is the evaluator's state with the envelopes lifted out, and is empty for a
// run nothing has decided yet.
Document json.RawMessage
// Seq is what the next decision has to be written against.
Seq int
Inputs map[string]any
Trigger agk.TriggerKind
WakeAt time.Time
// ReplayOf and ReplayFrom are the run this one replays and the step it replays from, empty
// for a run that replays nothing: the evaluator starts the steps above that step in the
// state the run it replays left them.
ReplayOf agk.RunID
ReplayFrom agk.Step
// Context is what fired the run, frozen on it, which the evaluator is started with.
Context TriggerContext
// NamespaceVars are the namespace's variables the run read when it was created, which the
// evaluator is started with under the file's own. Read only while nothing has decided the run,
// since the document carries the vars it was started with from then on, and nil otherwise.
NamespaceVars map[string]any
// TriggeredBy is who the run is attributed to, as a grant names a principal, and empty where
// the row names nobody. It is who the controller asks about before it lets the run in, since
// "authorisation is re-evaluated when a run is created".
TriggeredBy string
// Version names the row as it was read: the transaction that last wrote it, which any write
// of it moves, a decision's, a loss's clock or a cancellation request alike. Rewake is held to
// it.
Version string
// CancelRequestedAt is when somebody asked through the API for this run to be cancelled, and
// zero while nobody has. The request is the API's to write and the cancellation is the
// controller's to carry out, so a run holding one is a run the next pass ends.
CancelRequestedAt time.Time
// CreatedAt is when the run was created, by the database's clock: where its end-to-end
// latency runs from, a wait for its concurrency group included.
CreatedAt time.Time
// MaxRunDuration is its namespace's max_run_duration, written as a timeout is, and empty
// where the namespace sets none. Read with the run, since every pass is decided under the
// bound that holds when it is taken.
MaxRunDuration string
// CallerRun is the run whose call started this one, empty for a run nothing called, and
// Depth how deep in a chain of calls it is.
CallerRun agk.RunID
Depth int
}
Evaluation is a run as the controller picks it up.
type Event ¶
type Event struct {
Namespace string
ID string
Kind Kind
Run agk.RunID
State agk.RunState
// StartedBy is the principal the run was attributed to, and is empty where a schedule
// or an event started it: "Runs started by a schedule, a webhook or an event are
// attributed to the namespace service identity, not to the person who last edited the
// workflow."
StartedBy string
CreatedAt time.Time
}
Event is one thing worth waking somebody for.
type ExchangeCode ¶ added in v0.3.0
type ExchangeCode struct {
// Hash is the SHA-256 of the code's value, which the caller computes.
Hash []byte
// Login signed in with Credential, a credential of theirs, which says at the exchange what the
// sign-in may mint, as it says what the session it opened may do.
Login string
Credential string
// CodeChallenge is the SHA-256 of agk login's verifier, base64url without padding, as the
// sign-in page was opened with it.
CodeChallenge string
IssuedAt time.Time
ExpiresAt time.Time
}
ExchangeCode is a code a sign-in minted, and what it was minted for.
type ExitCodeCount ¶ added in v0.6.0
ExitCodeCount is how many attempts ended with one exit code, or with none where ExitCode is nil: lost with their runner, or stopped before a container reported one.
type Firing ¶ added in v0.5.0
type Firing struct {
// For is the occurrence, the instant trigger.scheduled_for reads, and At when it fired.
For, At time.Time
// Run is the run it started, or Skipped says why it started none.
Run agk.RunID
Skipped string
// Next is the occurrence the schedule is due for from now on, and FireAt when it fires.
Next, FireAt time.Time
}
Firing is what became of one occurrence of a schedule, and when it comes round next.
type GrantFile ¶ added in v0.4.0
type GrantFile struct {
From string `json:"from"`
To string `json:"to,omitempty"`
Mode string `json:"mode,omitempty"`
}
GrantFile is one selector of a step's files, as the workflow wrote it: a path or glob of the tree, where it is relocated to, and the mode it is given.
type GrantInput ¶
type GrantInput struct {
Port agk.Port `json:"port"`
Digest string `json:"digest"`
Items int `json:"items"`
Size int64 `json:"size,omitempty"`
}
GrantInput is one input port's envelope, named by digest.
Size is what its object is counted at. The envelope a shard is handed is often one nothing else names, a slice of a fan-out or a port fed by the step's own inputs, and it is kept so that the task can be read back as it ran, "so an incident is reproducible without extra instrumentation". An object nothing counts is one the collector never sees and the purge never lowers, so it would outlive its run's retention; and one shared with another run's envelope would go with that run's.
type GrantScope ¶
type GrantScope struct {
Run agk.RunID `json:"run,omitempty"`
Step agk.Step `json:"step,omitempty"`
// Workflow and Commit are the version the task runs, which is what names its tree: "the
// controller resolves a commit to a tree and the runner fetches content-addressed objects
// with the task's grant". Written here rather than read off the run at redemption, so that
// what a runner is handed is what the controller decided and not what a second lookup
// found, and so that a runner holding a grant can reach one version's files and no other.
Workflow string `json:"workflow,omitempty"`
Commit string `json:"commit,omitempty"`
Inputs []GrantInput `json:"inputs,omitempty"`
Secrets []GrantSecret `json:"secrets,omitempty"`
// Params are the task's parameters as the controller resolved them, a secret as the reference
// it is and never its value. A redemption answers none of them, since the task message carries
// them to the runner; they are kept so that the run can say what each task was dispatched with,
// "so an incident is reproducible without extra instrumentation", and are absent from a grant
// written before they were kept.
Params map[string]any `json:"params,omitempty"`
// Files are the step's files, which narrow and relocate the tree the redemption answers:
// none is the whole tree. Written with the version rather than read off its graph at
// redemption for the reason Workflow and Commit are, and absent from a grant written before
// the redemption served them, which is answered the whole tree as it was then.
Files []GrantFile `json:"files,omitempty"`
}
GrantScope is what one grant may be turned into, and the whole of it.
It is what the task was dispatched with, written by the controller at the moment it decided: the version whose tree the task sees under /agk/repo, the envelopes on each input port, named by digest, and the secrets the step asked for, named with where they go and never valued. A redemption answers from this and from nothing else, which is what makes "refusing anything the task does not name" a comparison rather than a promise.
type GrantSecret ¶
GrantSecret is one secret the step asked for, by name, and the path the value is written at.
The mount travels with the name because it is not always /agk/secrets/<name>: a brick manifest may ask for a secret somewhere else under /agk/secrets/, and the value and the path it belongs at have to reach the runner as one entry. Only the controller read the manifest, so only the controller can write it down.
type Granted ¶
type Granted struct {
Task agk.TaskID
Clear string
ExpiresAt time.Time
// Rewrite are the digests of input envelopes whose objects a sweep had claimed when the
// grant counted its reference onto them, or which had no row until it did. The reference is
// safe, and the bytes may be what the sweep is about to delete or has deleted, so the caller
// writes them again.
Rewrite []string
}
Granted is a grant as it was issued: the clear value, once, and when it stops working.
type Hook ¶ added in v0.5.0
type Hook struct {
Workflow string
Position int
Commit string
Declared json.RawMessage
}
Hook is a webhook armed: the workflow whose default branch declares it, where in its list, and what it declares with the values in force.
type HookCredential ¶ added in v0.5.0
type HookCredential struct {
Version int
Secret json.RawMessage
Certificate []byte
WrittenBy string
WrittenAt time.Time
// Storage is the storage name of the namespace, which a secret is sealed under (NS.Storage),
// read beside it by HookCredential.
Storage string
}
HookCredential is what one webhook checks a caller against: the secret an hmac signature is made with, sealed, at the write it is bound to, and the SHA-256 of the certificate an mtls caller presents. Either is empty where none was written.
type HookTaken ¶ added in v0.5.0
type HookTaken struct {
Namespace, Path, Method string
// Holder is the workflow that has armed it.
Holder string
}
HookTaken is a push arming a webhook whose path and method another workflow of the namespace has armed: "within a namespace a path and a method answer one trigger".
type ImagePin ¶ added in v0.4.0
type ImagePin struct {
// Reference is the image as a step writes it, by a tag, and Image the reference by digest of
// the same repository it is pinned to, name@sha256:<hex>.
Reference string
Image string
PinnedBy string
PinnedAt time.Time
}
ImagePin is one image tag of a repository and the reference by digest it is pinned to.
type Images ¶ added in v0.4.0
Images are what RecordImages is asked to record: pins by reference, and manifests by the reference by digest of their image.
type ImagesRecorded ¶ added in v0.4.0
type ImagesRecorded struct {
Pins []PinMoved
Manifests []ManifestRecorded
}
ImagesRecorded is what RecordImages changed: the pins it created or moved, and the manifests it recorded or replaced, each in order. What it was asked to record again as it stood is in neither.
type JoinToken ¶
type JoinToken struct {
ID string
Pool string
Labels []string
// Clear exists once, in the answer to the request that created it.
Clear string
IssuedBy string
IssuedAt time.Time
ExpiresAt time.Time
}
JoinToken is what an administrator hands to a machine that is about to become a runner.
type Joined ¶
type Joined struct {
Runner string
Pool string
Credential string
RotateBy time.Time
// Labels are the labels the runner joined with, those it claimed, and IssuedBy who issued
// the join token it spent: what the join is recorded with, since the machine is nobody a
// grant names and the token is how somebody let it in.
Labels []string
IssuedBy string
}
Joined is what it gets back: an identity, and a credential that exists once.
type Joining ¶
type Joining struct {
Token string
Labels []string
// PublicKey is the public half of the keypair the host generated, which is the runner's
// identity across restarts and what a rotation is signed against. The private half never
// leaves the host.
PublicKey ed25519.PublicKey
// What a machine says about itself is what only the machine knows: "the public key, the
// labels it claims, its AGK_RUNNER_NAMESPACES, its capacity in vCPU, memory and disk, its
// architecture and its agent version". What it is allowed is its token's and its pool's,
// and its own namespaces only narrow that.
CPU int
MemoryBytes int64
DiskBytes int64
Architecture string
AgentVersion string
// Namespaces is the host's own narrowing, nil where it narrows nothing. It may name only
// namespaces its pool accepts: it narrows and never widens.
Namespaces []string
// Containment is what the host can prove about how its containers are contained, nil
// where it said nothing.
Containment *Containment
}
Joining is what a machine says about itself when it presents a token.
type Kind ¶
type Kind string
Kind is what happened.
const ( // Failure is a run that did not work. Not a run somebody cancelled: that is a // completion, because somebody meant it. Failure Kind = "failure" // ApprovalRequested is a run suspended on a human decision. Nothing emits it yet, // because nothing in the language can suspend a run; the kind exists so that the group // that teaches it to does not also have to widen a check constraint. ApprovalRequested Kind = "approval_requested" // Completion is a run that ended, however it ended. The page scopes it to "a run the // recipient started", which the API resolves from StartedBy: who wants it is a // preference and a grant, and neither is the controller's. Completion Kind = "completion" )
type LatestRun ¶ added in v0.6.0
type LatestRun struct {
Run agk.RunID `json:"run"`
State agk.RunState `json:"state"`
TriggerKind agk.TriggerKind `json:"trigger_kind"`
CreatedAt time.Time `json:"created_at"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
}
LatestRun is a workflow's newest run, by when it was created, as a listing of workflows names it.
type LibraryFiles ¶ added in v0.4.0
LibraryFiles are the files of a library a workflow include read, at the commit its ref resolved to.
type Listed ¶ added in v0.4.0
type Listed struct {
Commit string
Parent string
Author string
CreatedAt time.Time
Source string
// Library says the commit is a library's, which nothing runs.
Library bool
}
Listed is a version as a listing names it: its commit, its parent, who pushed it, when, and how.
type ListedRun ¶ added in v0.6.0
type ListedRun struct {
RunSummary
Steps []StepStrip `json:"steps"`
}
ListedRun is a run as a listing answers it: its record, and its steps in the order they started, each with its verdict and when it started and ended, which a listing draws as a strip whose segments are as wide as the steps took, so that where a run failed and how long each part of it lasted are read before its colours are.
type ListedWorkflow ¶ added in v0.6.0
type ListedWorkflow struct {
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
Latest *LatestRun `json:"latest,omitempty"`
}
ListedWorkflow is one workflow as a namespace's listing answers it to whoever reads its runs: its name, when it was created, and its newest run, nil where it was never run. Nothing of its repository or its file, which workflow:read guards.
type Listening ¶ added in v0.5.0
type Listening struct {
Namespace, Workflow string
Position int
Commit string
Declared json.RawMessage
}
Listening is an event trigger armed to hear a namespace: where it is armed, the version that armed it and what it declares.
type LiveChange ¶ added in v0.6.0
type LiveChange struct {
Kind ChangeKind
Namespace string
Workflow string
Run string
Recipient string
}
LiveChange is one notification on LiveChannel, read.
func ParseLiveChange ¶ added in v0.6.0
func ParseLiveChange(payload string) (LiveChange, error)
ParseLiveChange reads a payload the triggers of migration 0067 sent.
type Log ¶
type Log struct {
Namespace string
Task string
URI string
// Keys are objects its lines were written to, for the caller to delete before it
// confirms. A log written in many chunks may be handed over across several claims.
Keys []string
}
Log is one task's log, as the database holds it: a URI and never the lines.
type LogChunk ¶
type LogChunk struct {
Seq int
FirstLine int
Shipped int
ShippedDigest string
// Lines and Bytes are what was written, and Key the object holding them with Digest the
// digest of its bytes, both empty where the cap kept none of the chunk's lines.
Lines int
Bytes int64
Key string
Digest string
}
LogChunk is one chunk of a log as the index holds it: where it sat in what the runner shipped, what it carried, and what of it was written where.
type Loss ¶
type Loss struct {
Task agk.TaskID
Requeue int
At time.Time
// Pool is the pool of the runner that held it, which is where the loss is charged: a loss
// is the infrastructure's, and the pool is the part of it an operator can look at.
Pool string
}
Loss is one dispatch the heartbeat declared lost: the key, which dispatch of it, and when.
type ManifestRecorded ¶ added in v0.4.0
ManifestRecorded is a manifest RecordImages recorded or replaced: its SHA-256, and Was the SHA-256 of the one it replaced, empty where the repository held none for the image.
type Memo ¶ added in v0.4.0
Memo is one cache entry: the key, the run and step whose task published under it, and each port it published.
type MemoPort ¶ added in v0.4.0
type MemoPort struct {
Port agk.Port `json:"port"`
Digest string `json:"digest"`
Items int `json:"items"`
Size int64 `json:"size"`
}
MemoPort is one port a cached task published: its envelope by the digest it is stored under, written sha256:<hex> as a run's document writes one, its count of items and its size.
type Migration ¶
type Migration struct {
// Name is the file, which begins with the number that orders it.
Name string
// SQL is what it does.
SQL string
}
Migration is one file of the schema.
func Migrations ¶
Migrations are the schema in the order it is applied.
The order is the file name's leading number, and it is lexical rather than numeric on purpose: the names are zero padded, so the two agree, and a name that broke the padding would sort visibly wrong in a directory listing rather than invisibly wrong here.
type Move ¶ added in v0.4.0
type Move struct {
Namespace, Workflow, Target string
AskedBy string
AskedAt time.Time
// Repository is the key its packs are kept under, which the move keeps.
Repository string
// Storage and TargetStorage are the storage names of the namespace it leaves and of the one it
// goes to, which their objects are kept under (NS.Storage): the move copies from the one to the
// other.
Storage, TargetStorage string
}
Move is a move asked and not yet carried out.
type MoveObjects ¶ added in v0.4.0
type MoveObjects struct {
Digests []string
Logs []string
Indexed []string
Packs []string
Ready bool
}
MoveObjects are what a move copies under the target's keys before it is carried out: the digests of the objects the workflow's rows count, without the sha256: they are stored under, the keys of its logs, and the names of its packs. Ready is false while it cannot be carried out yet, a run of it not finished or a pack of it being collected, and the copying waits with it.
Indexed are the keys of Logs whose chunks were indexed as they were read, whose objects were written then: the move is carried out only where no other chunk has been indexed since, which a task still stopping as its run ended can ship, and which the copy could not have seen.
type Moved ¶ added in v0.4.0
type Moved struct {
// Done is false where the move could not be carried out yet, or is no longer asked.
Done bool
// MustWrite are the digests of objects the target's collection had claimed, or held no row of,
// when the move counted them there: their bytes are written again under the target's keys,
// as a version's are (Saved.MustWriteBytes, Saved.Recorded).
MustWrite []string
}
Moved is what carrying a move out settled.
type MovedObject ¶ added in v0.4.0
type MovedObject struct {
Namespace, Key string
}
MovedObject is a key a move left under the namespace it left.
type NS ¶
type NS struct {
// contains filtered or unexported fields
}
NS is a handle on one namespace, inside one transaction.
Every statement it issues runs with agentiik.namespace bound, so the policies see the namespace whether or not the statement mentions it. A statement that forgets the column reads that namespace's rows rather than everybody's, and a statement that writes another namespace's name is refused.
func (*NS) AccessGrants ¶ added in v0.3.0
AccessGrants is every grant of this namespace, expired ones included, ordered by when they were written: the listing a principal holding grant:manage reads.
func (*NS) AccessGrantsAt ¶ added in v0.3.0
func (n *NS) AccessGrantsAt(ctx context.Context, workflow string, now time.Time) ([]access.Grant, error)
AccessGrantsAt answers the grants and denies that apply at one scope of this namespace and have not expired at now, each with the scope it was written at: those written on the namespace, which every workflow in it inherits, and where workflow is not empty, those written on that workflow; the namespace's first, then each in the order written. A namespace nobody created is ErrNoNamespace, and a workflow it does not hold ErrNoWorkflow, so that a listing tells the absent from the empty.
func (*NS) AccessGrantsFor ¶ added in v0.3.0
func (n *NS) AccessGrantsFor(ctx context.Context, p access.Principal, workflow string, now time.Time) ([]access.Grant, error)
AccessGrantsFor answers the grants of this namespace that may apply at now to p, its own and its groups', on workflow: those on the namespace and those on that workflow, not expired. An empty workflow asks about the namespace alone, and answers the grants on the namespace.
func (*NS) Arm ¶ added in v0.5.0
func (n *NS) Arm(ctx context.Context, workflow, commit string, entries []Entry, by string, at time.Time) error
Arm replaces what a workflow has armed by entries, the triggers commit declares, and records it as armed, by who at at. An empty commit disarms everything: a default branch with no version to run, or a version that is a library.
An entry declared again, the same kind with the same Declared, keeps its row's state: a schedule its next occurrence and its last firing, so that a push at 05:59 neither skips nor doubles the run due at 06:00; and a webhook answering the same path with the same method keeps the failures counted against it, whatever else about it changed. Each entry newly armed is recorded as trigger.arm and each no longer armed as trigger.disarm, with the workflow as the target; one declared again is neither, since a push that leaves the triggers as they were would otherwise record every one of them twice and bury the changes the log is read for.
A webhook whose path and method another workflow of the namespace has armed is a *HookTaken, and nothing is written.
func (*NS) ArmedBy ¶ added in v0.5.0
ArmedBy is what a workflow has armed, by kind and then by position.
func (*NS) ArmedCommit ¶ added in v0.5.0
ArmedCommit is the commit whose triggers a workflow has armed, empty where none has been.
func (*NS) Audit ¶
Audit appends r to the audit log, in this namespace, in this handle's transaction: the entry commits with the act and is rolled back with it.
func (*NS) CheckVersion ¶
CheckVersion answers what SaveVersion would refuse a version for, and records nothing.
ErrOtherTree is the answer that matters. SaveVersion gives it too, and gives it too late for a push: by then the files of the tree are in the store, and a push refused there has left objects behind it that nothing counts and the collector therefore never sees, as often as anybody cares to push one commit with other files. So a push asks here first, before it writes a byte. A commit not recorded yet is nil, since the version is new, and so is one recorded with this same tree, since pushing it again changes nothing.
func (*NS) ContextOf ¶ added in v0.5.0
ContextOf is what fired a run, frozen on it, which a replay of the run is written with.
func (*NS) CreateRun ¶
CreateRun writes a run and one row per step of its graph, and refuses one past the namespace's max_runs_per_hour with a *RunsPerHourReached.
The run is queued and not running, because "Created, waiting on a concurrency lock or on namespace quota" is what queued means and admission has not happened yet. It carries no evaluation document for the same reason: a document is what a decision leaves behind, and nothing has decided.
The runs an hour are counted here and nowhere else because every run is created here, whatever its trigger: an entry point added later is limited without a counter of its own.
func (*NS) CreateWorkflow ¶ added in v0.4.0
func (n *NS) CreateWorkflow(ctx context.Context, name, branch string, protected bool, by string, at time.Time) (WorkflowRecord, error)
CreateWorkflow records an empty repository: the workflow, and its default branch unborn, protected or not, so that whether pushing to it takes grant:manage is settled before its first push. A name the namespace holds is ErrWorkflowExists, whoever created it and however.
func (*NS) Declaration ¶
Declaration is one secret the namespace declares, or ErrNoDeclaration.
func (*NS) Declarations ¶
func (n *NS) Declarations(ctx context.Context) ([]Declaration, error)
Declarations are every secret the namespace declares, by name.
func (*NS) Declare ¶
func (n *NS) Declare(ctx context.Context, d Declaration) (Declaration, bool, error)
Declare writes one declaration, replacing the one of that name if there is one, and answers it as it was stored and whether it is new.
One secret at a time and never the set, so that two writers each declaring their own secret cannot undo each other. Replacing is the ordinary case rather than a conflict: a declaration moved to another path is the same secret declared again.
The time answered is the one the row holds, in UTC, and not the one it was given: PostgreSQL keeps microseconds where a clock may give nanoseconds, so answering the clock would make a declaration read differently the moment after it was written, and a client comparing the two, as Terraform does after every apply, would see it change.
func (*NS) DefaultCommit ¶ added in v0.5.0
DefaultCommit is the commit a run naming none runs: the default branch's head, or while it is unborn the latest version a tree push recorded, or ErrNoVersion where there is neither.
func (*NS) DeleteWorkflow ¶ added in v0.4.0
func (n *NS) DeleteWorkflow(ctx context.Context, workflow, by string, at time.Time) ([]agk.RunID, error)
DeleteWorkflow marks a workflow deleted, by and at, asks to cancel every run of it still going, brings the expiry of every run's envelopes, logs and artifacts to at, and answers the runs it asked to cancel, for the controller to be woken for each. ErrNoWorkflow where the namespace holds no such workflow, or one deleted already.
func (*NS) Deleted ¶ added in v0.4.0
Deleted says whether workflow is one deleted and not yet purged, which is answered as absent: the authorizer holds nothing over it for anybody.
func (*NS) Delivered ¶
Delivered spends the fetch held until held, whose transfer completed, and retires the reference where that was the last: "Once consumed, the reference is gone immediately rather than at the next sweep."
Spent even where the hold has lapsed and been dropped, since the bytes went all the same.
func (*NS) Delivery ¶ added in v0.5.0
func (n *NS) Delivery(ctx context.Context, path, method, id string, at time.Time, forget time.Duration) (agk.RunID, bool, error)
Delivery takes the delivery its sender named id for the webhook at path and method, at, and says whether it was taken already, with the run that delivery started. Deliveries older than forget are let go first: a request is refused outside its window, so none of them can come again.
Taken in the transaction the run is created in, so that a delivery whose run was refused is not taken, and its sender's retry is answered as the first request would have been. Two copies of one delivery arriving together take turns on its row, and the second is answered with the run of the first once the first commits.
func (*NS) DeliveryRun ¶ added in v0.5.0
DeliveryRun records the run the delivery id started.
func (*NS) EventFired ¶ added in v0.5.0
func (n *NS) EventFired(ctx context.Context, l Listening, at time.Time, run agk.RunID, skipped string) error
EventFired records on the event trigger l names what an event it matched became: the run it started, or why it started none, a skipped firing, "as a schedule's is". A trigger armed anew since it was read records nothing, since what it now declares is not what matched.
func (*NS) EventRuns ¶ added in v0.5.0
EventRuns records how many runs the event source and id name started, what one published again is answered with.
func (*NS) EventTaken ¶ added in v0.5.0
func (n *NS) EventTaken(ctx context.Context, source, id, publisher string, at time.Time, forget time.Duration) (int, bool, error)
EventTaken takes the event source and id name as published into this namespace at at, by publisher, and answers false; or, where it was taken already within forget, how many runs it started, and true. Those taken longer ago are let go first, so that the table holds a day of events rather than every event ever published.
func (*NS) Fired ¶ added in v0.5.0
Fired records what became of the occurrence d was due for and moves the schedule on to the next, in the transaction Held locked its row in.
func (*NS) FirstLoad ¶ added in v0.6.0
FirstLoad is when the namespace first created or refused a run before before, as its quota statistics count them, and the zero time where it has done neither.
func (*NS) ForgetSealed ¶
ForgetSealed removes the value the namespace keeps under a name, and is not an error where it keeps none.
The sealed value goes and the row stays, holding its version and nothing else, so that the next write of the name is sealed at a version no earlier write had.
func (*NS) FormerNames ¶ added in v0.6.0
FormerNames are the names the namespace held before it was renamed, in the order it left them, and none for one never renamed, or one that does not exist.
func (*NS) GitHosted ¶ added in v0.4.0
GitHosted says whether git hosts a workflow's repository: whether any of its refs points at a commit, which only a git push makes. The tree push asks it under the repository's lock, since a version it made from then on would be one no ref reaches and no pack holds.
func (*NS) GrantAccess ¶ added in v0.3.0
GrantAccess writes a grant in this handle's namespace, which its scope names, at its GrantedAt or, where that is zero, the database's now. The identifier is the caller's, as a run's is. A grant access.Grant.Validate refuses is refused here, a principal nobody created is ErrNoPrincipal, and a workflow the namespace does not hold is ErrNoWorkflow.
func (*NS) Held ¶ added in v0.5.0
Held reads a schedule's row under a lock, where it is still due for the occurrence d names, and ErrScheduleMoved where it is not: the first thing a firing does in its transaction, so that two passes firing one occurrence take turns and the second finds it moved on.
func (*NS) HoldRepository ¶ added in v0.4.0
HoldRepository takes the lock a push takes on a workflow's row, FOR NO KEY UPDATE, which every writer of a repository's refs, packs and images takes before it writes anything else, so that two of them never wait on each other's rows in two orders. ErrNoWorkflow where there is none.
func (*NS) HookCredential ¶ added in v0.5.0
func (n *NS) HookCredential(ctx context.Context, workflow, path, method string) (HookCredential, error)
HookCredential is what the webhook of workflow at path and method checks a caller against.
func (*NS) HookCredentials ¶ added in v0.5.0
func (n *NS) HookCredentials(ctx context.Context, workflow string) (map[[2]string]HookCredential, error)
HookCredentials are the credentials written for the webhooks of workflow, by method and path, for a listing to say which are written, when and by whom, and never what.
func (*NS) HookHolder ¶ added in v0.5.0
HookHolder is the workflow of this namespace, other than workflow, that has armed a webhook answering path with method, or empty where none has. It is what a push moving the default branch is judged against, before any ref moves.
func (*NS) HookRefused ¶ added in v0.5.0
HookRefused counts one request the webhook at path and method refused for want of a caller it could prove: "a sudden run of them is an unannounced rotation or somebody guessing".
func (*NS) ImagesOf ¶ added in v0.4.0
func (n *NS) ImagesOf(ctx context.Context, workflow string, named *Images) ([]ImagePin, []BrickManifest, error)
ImagesOf answers the pins of the repository, by reference, and its manifests, by image, in C's collation, byte by byte, whatever collation the database was created with: every one where named is nil, and those it names otherwise. ErrNoWorkflow where the namespace holds no workflow of that name.
func (*NS) LogChunks ¶
LogChunks reads the chunks of one dispatch's log that hold lines, after seq after and at most limit of them, in order: what a reader who has had everything up to after reads next.
func (*NS) MakeRoom ¶ added in v0.3.0
MakeRoom holds room for one write, or refuses it with a *NoRoom.
Nothing is held, and nothing is locked, where the namespace sets no max_artifact_bytes, as before v0.3.0, or already holds the object as a live artifact: the bytes are then bytes it counts, and a replay writing what it wrote before is refused nothing. An object another write is making room for is held again, to what this write may take beyond the other's room, so that neither write's failure leaves the other's bytes counted by nothing.
The namespace's row of artifact_room is locked first, so that two writes in the namespace at once make their room one after the other, the second counting what the first made once the first has committed.
func (*NS) Manifest ¶ added in v0.4.0
Manifest answers the brick manifest the repository holds for an image by digest, a tag written beside the digest or not, or ErrNoManifest.
func (*NS) Moving ¶ added in v0.4.0
Moving says whether a move of the workflow was asked and not carried out, for a caller that answers so before it writes anything.
func (*NS) NamespaceVarsOf ¶ added in v0.6.0
NamespaceVarsOf are the namespace's variables a run read when it was created, which a replay of it is written with, so that it reads what the run read rather than what is true now. Never nil: a run that read none, or one from before v0.6.0, answers an empty map, which a replay reads as none, as the run did, rather than as variables to read now.
func (*NS) NotWritten ¶ added in v0.3.0
NotWritten lets go of a write whose bytes never arrived, which there is nothing of to keep from the collector, so that a writer refused its bytes leaves no row behind it for a day.
func (*NS) NotifyRun ¶
NotifyRun tells the controller a run is worth looking at.
The payload is the identifier and nothing else, which keeps it far below the documented eight thousand byte limit and keeps the notification what it is: a latency optimisation. The controller's sweep is the correctness guarantee, so a notification that is never delivered, to a controller that was restarting, costs latency and not a run.
It is on the namespaced door because the API sends it in the same transaction that writes the run, which is what makes the two one fact: PostgreSQL delivers the event only when that transaction commits.
func (*NS) Output ¶
Output reads one of a run's workflow outputs.
runs.outputs names the step and the port each output is a view of, and steps.ports holds the digest that port published, which is where the envelope is: the database keeps its digest and never its bytes.
func (*NS) PackLive ¶ added in v0.4.0
PackLive makes a received pack one a fetch reads, in the transaction that moves the refs onto what it holds, under the same lock on the workflow's row. A pack no longer receiving, which the collection took once it had been receiving past the grace, is ErrNoPack, and the push that wrote it fails rather than naming objects the store no longer holds. One live already stays live.
func (*NS) Pin ¶ added in v0.4.0
Pin answers the reference by digest the repository's tag is pinned to, or ErrNoPin.
func (*NS) Present ¶ added in v0.3.0
Present answers nil where this namespace exists and, where workflow is not empty, holds that workflow, and ErrNoNamespace or ErrNoWorkflow where not. A route an administrator may reach for a namespace nobody created tells the absent from the empty with it.
func (*NS) PublishedPorts ¶
PublishedPorts reads back what a step published.
func (*NS) QuotaStatistics ¶ added in v0.6.0
QuotaStatistics counts what the namespace asked of its quotas, bucket by bucket, every bucket answered, oldest first. A bucket that ended before the namespace's max_retention_days, where it sets one, counts nothing, as a series of its runs does: "a range reaches back as far as the namespace keeps its runs, and no further".
Read through the namespace's own handle, since what it counts is every workflow of the namespace alike, as a quota bounds them, and whoever reads the namespace reads it.
func (*NS) ReceivePack ¶ added in v0.4.0
ReceivePack records a pack a push is about to write into the repository of workflow, and answers the repository's key, which the pack's keys are made of.
It is recorded receiving before a byte of it is written, in a transaction of its own, so that a file under git/ always has a row naming it: one a push died writing is collected with its row once it has been receiving past the grace, and one a push is writing is never taken for anything else. A pack of the same name is the same bytes, since its name is their checksum: one receiving is receiving again from now, one live stays live, and one superseded is receiving again, so that the collection, which claims a pack only while it is superseded or receiving past the grace, leaves the bytes this push is about to write alone. One the collection has claimed already is ErrPackCollected: its files are going, and the push is sent again once they are gone. One not live takes the size and the count given now, which are those of the bytes about to be written: a write refused for a size that was not theirs leaves nothing to hold the next one to.
func (*NS) RecordImages ¶ added in v0.4.0
func (n *NS) RecordImages(ctx context.Context, workflow, by string, at time.Time, images Images) (ImagesRecorded, error)
RecordImages records pins and manifests of one repository as by at at, now where at is zero, all of them or none, and leaves every other pin and manifest of the repository as it was, so that two pushes of one workflow never drop each other's. It answers what it changed, in order: a pin named again at the digest it holds is left alone, its pinned_by and pinned_at included, and a manifest recorded again with the same bytes is too.
A manifest recorded again with other bytes replaces the one held, so that one recorded wrong, by a client with a bug, is put right by recording it again rather than left to refuse every push after it; what it replaced is answered, for the caller to record in the audit log, since a manifest is what a version made from it holds of the brick, its ports, its parameters and where its secrets are mounted. A failure keeps nothing of the set, even where the caller's transaction goes on and commits: the set is written under a savepoint of its own, as UpdateRefs writes a push's refs. ErrNoWorkflow where the namespace holds no workflow of that name.
Every row is written in reference and image order, so that two sets naming the same entries lock them in one order and never deadlock.
func (*NS) RemoveVariable ¶ added in v0.6.0
RemoveVariable removes one variable, or answers ErrNoVariable where there was none.
func (*NS) RenameWorkflow ¶ added in v0.4.0
RenameWorkflow gives a workflow another name within its namespace: "a rename carries everything at once: versions, refs, runs, grants and triggers answer at the new name from the answer on, the old name is free". One statement on the workflow's row, which every key naming it carries through (migration 0053), the grants of the tasks of its runs, which name the version their task runs by the workflow's name in their scope, so that a task dispatched before the rename redeems after it, and the namespace's variables selected for it, which name it in a list no key carries. Under the lock every writer of the repository takes, so that a push and a rename are one before the other.
ErrNoWorkflow where the namespace holds no such workflow, or one deleted; ErrWorkflowExists where it holds one under the new name, and ErrWorkflowPurging where one deleted under it is still being purged.
func (*NS) Repacked ¶ added in v0.4.0
Repacked makes the pack a repack wrote live in place of the packs it replaced, under the lock every push takes to move its refs, and marks those superseded from now: a fetch that began before reads them for the grace, and one that begins after reads the new pack. A pack it replaced that a push has made live since, or that is no longer live, is left as it is. The new pack no longer receiving, which the collection took past the grace, is ErrNoPack.
func (*NS) Repository ¶ added in v0.4.0
Repository reads a workflow's repository: its key, its default branch, its refs and its live packs.
The refs are read before the packs, which is what makes the two agree without a lock. A pack is made live in the transaction that moves refs onto what it holds, and superseded only once a pack holding everything it did is live, so packs read after the refs hold every object the refs name. Read the other way round, a push committing between the two reads would name a commit no pack listed holds.
func (*NS) RequestCancel ¶
func (n *NS) RequestCancel(ctx context.Context, run agk.RunID, at time.Time) (agk.RunState, bool, error)
RequestCancel records that a run is to be cancelled, and answers the state it is in and whether this was the first request, which the audit log records as the one that changed something.
It asks and decides nothing. Ending a run and stopping what it holds is one decision, and it is the controller's, which reads the request on its next pass: the API writes down the moment it was asked and notifies, as it does for a run it starts. A run that has already ended is left as it is and answered in the state it ended in, so that the API wakes nobody for it; what the API says back is its own to decide, and it says nothing of the state. Asking again keeps the first moment.
An identifier outside the alphabet runs are minted in is no run, as it is for Locate.
func (*NS) Reserve ¶
func (n *NS) Reserve(ctx context.Context, u agk.URI, hold time.Duration) (Resolved, time.Time, error)
Reserve holds one fetch of a budget for a transfer about to begin, until the instant it answers, which is also what the transfer names it by to Delivered or Release.
"A fetch counts when the response completes", which is after the bytes have gone, and two fetches of the last one that each read the budget before either counted would both be served it. So a fetch is held before the transfer, where nobody else can take it, and the transfer ends with Delivered where it completed and with Release where it did not: a transfer interrupted, refused or never begun does not consume the artifact, and does not keep it from anybody past its hold. Nothing of the database is held while the bytes go.
A reference never written, retired or past its duration answers as Resolve does; one with no budget is an error, since there is nothing to hold; one whose fetches left are all held answers ErrInFlight.
func (*NS) Resolve ¶
Resolve turns agk://run/<run>/<step>/<port>/<name> into the physical key it addresses.
A reference that has expired or been collected resolves to what it was, with ErrGone beside it: the name, the size and the digest are what the run detail keeps showing, and the error is what tells an API to answer 410 rather than 404. So does a reference whose duration has run out and which no sweep has retired yet, as Expired: "a duration bounds how long they may be fetched", and a sweep that has not come round yet does not lengthen it.
func (*NS) ResolveRef ¶ added in v0.5.0
ResolveRef is the commit a ref names in a workflow's repository: a branch or a tag by its short name or in full, or a commit named in full that is a version. A ref naming nothing, or two things, is a *RefUnresolved.
func (*NS) RevokeAccess ¶ added in v0.3.0
RevokeAccess removes the grant id written at one scope of this namespace, on the namespace where workflow is empty and on that workflow where it is not, and answers it as it was. One written at the other scope is ErrNoAccessGrant, as one nobody wrote is: a grant is revoked where it was written, so that whoever may share one workflow revokes what was written on it and nothing its namespace gives. A revoked grant is gone rather than kept: the audit log is where who granted what and who took it back is kept.
The namespace is held for key share first, as a grant written in it holds it, so that a removal of the namespace, which holds it for update and then takes its grants, and the owners told of a deny revoked (NS.TellOwners), which hold it too, take it in the order every other act does: a revocation holding the grant and waiting on the namespace, while the removal holds the namespace and waits on the grant, is a deadlock.
func (*NS) RunState ¶ added in v0.5.0
RunState is the state run is in now, which a caller waiting on it reads.
func (*NS) SaveVersion ¶
SaveVersion records one commit of one workflow, and keeps the objects its tree names alive.
A commit already written is left exactly as it was, and that is the point rather than a convenience: "a version is a commit", so the same commit pushed twice is the same version, and a second push that overwrote it would make a run pinned to that commit mean something else than it did when it started. The same commit with another tree is ErrOtherTree rather than silence, because it is the one case where leaving the row alone would tell the pusher their files were recorded when they were not.
A version that is new raises one reference per distinct digest its tree names, in this transaction, which is what keeps the collector off those objects for as long as the version exists. A run pins its commit, "and neither does a replay of it six months on", which would mean nothing if the files under /agk/repo could be collected in between. The reference is raised by the same code an artifact and an envelope are counted by, so the three cannot disagree about what an object is kept for.
func (*NS) SaveVersions ¶ added in v0.4.0
SaveVersions records several versions in one transaction, each as SaveVersion records it, and raises the references of all of them in one pass, in digest order. Raised version by version, each in its own order, a push recording two versions and another push recording one could lock the rows of the objects they share in two orders, and deadlock.
func (*NS) SaveWorkflow ¶
SaveWorkflow records a workflow, or leaves the one that is there.
Idempotent, because pushing a second version of a workflow that already exists is the ordinary case and is not a request to change anything about the workflow itself.
A workflow it records is a repository created from v0.4.0, empty until its first git push: its default branch is recorded unborn and unprotected, as every repository is until an owner protects it, so that whoever holds workflow:write pushes to it as they did before v0.4.0. A branch no push could create, which only an API call written by hand names, is given no row, as the migration gives none: no push can move it, and it is unborn and unprotected either way.
func (*NS) SealedValue ¶
SealedValue is the value the namespace keeps under a name, as it was sealed, or ErrNoValue.
func (*NS) SetDefault ¶ added in v0.4.0
func (n *NS) SetDefault(ctx context.Context, workflow string, branch *string, protected *bool) (WorkflowRecord, WorkflowRecord, error)
SetDefault names a workflow's default branch, protects it or leaves it unprotected, or both, and answers the repository as it stood before and as it stands after. A nil field is left as it is.
A branch named the default is one the repository holds, or ErrNoBranch, where the repository holds any commit; while it holds none, it is the branch its first push will create, and the unborn row is renamed to it. Protection moves with the default branch, since only the default branch is protected: the branch it leaves is unprotected, and an unborn one it leaves is removed, since the only ref held without a commit is the default branch nothing was pushed to yet.
Under the lock every repository writer takes first, which a push takes to move its refs and under which it reads protection again (UpdateRefs): a push judged before a change of it is held to the change all the same.
func (*NS) SetVariable ¶ added in v0.6.0
SetVariable writes one variable whole, replacing the one of that name if there is one, and answers it as it was stored and whether it is new. A variable the namespace's bounds leave no room for is a *VariablesFull, and a namespace nobody created ErrNoNamespace.
One variable at a time and never the set, so that two writers each setting their own cannot undo each other. The namespace's row is locked before its variables are counted, so that two writers in one namespace count one after the other, the second counting the first's variable once it has committed: each would otherwise count what was there before both, and the two together could pass a bound neither passed alone. FOR NO KEY UPDATE, which leaves alone the key share a row naming the namespace takes, as withinRunsPerHour locks it.
The time answered is the one the row holds, in UTC, as Declare answers it and for its reason.
func (*NS) StepInput ¶
func (n *NS) StepInput(ctx context.Context, run agk.RunID, step agk.Step, attempt, shard int, port agk.Port) (Envelope, error)
StepInput reads the envelope one dispatch of a step was handed on one input port: the one of the attempt given, or of the last attempt dispatched where attempt is zero, and of the shard whose index is given, or of the step's one task where the step was not fanned out and shard is zero. Of a key requeued after a loss, the last dispatch, which was handed what the first was.
func (*NS) StepLog ¶
func (n *NS) StepLog(ctx context.Context, run agk.RunID, step agk.Step, since string, limit int) (StepLog, error)
StepLog reads where the log of one step stands, and at most limit of its dispatches in the order they were made, from the one since names on where it names one, since a reader has let go of those before it. The limit is what a reader held on the first shard of a fan-out of ten thousand reads each time, rather than the ten thousand.
The order is that of their identifiers: a task_id is minted when its row is, and a row is made when the evaluator hands the attempt out, so a dispatch made later sorts later and a reader that has gone past one never finds another made before it. Sorted byte by byte, as a ULID sorts, whatever collation the database was created with.
func (*NS) StepOutput ¶
func (n *NS) StepOutput(ctx context.Context, run agk.RunID, step agk.Step, port agk.Port) (Envelope, error)
StepOutput reads the envelope a step published on one port.
func (*NS) Storage ¶ added in v0.6.0
Storage is the namespace's storage name: the name it was created with, the first segment of the key of every object it holds, and the name its secrets' values and its webhooks' secrets are sealed under. "The storage name never changes, so a rename moves no byte however much a namespace holds, and a value sealed in it still opens." It is the namespace's name for every namespace never renamed, and the name itself for one that does not exist, whose keys nothing holds.
Read once per handle and kept, since it never changes.
func (*NS) Stored ¶ added in v0.3.0
Stored settles room held for an object whose bytes are in: it counts their size, which the bound was the most of, until it lapses.
func (*NS) TaskLog ¶
TaskLog reads one dispatch's log as a reader follows it: where it stands, and the chunks that hold lines, in order. A dispatch that has shipped nothing is ErrNoLog.
GET /api/v1/runs/{id}/steps/{step}/logs follows a whole step instead, with StepLog and LogChunks, which read a chunk once rather than every chunk each time the log moves on.
func (*NS) TellOwners ¶ added in v0.3.0
TellOwners writes AdminAccessWidened, about what an administrator did in this namespace, to each of the namespace's owners but the one who did it, and answers who was told, by name.
"The owner told is the principal the namespace's record names. A namespace from before v0.3.0 names none: it becomes shared ... and every principal holding the owner role on it is told instead", by a grant on the namespace, not expired at what.At, a deny beside it leaving the role held. A group among them is told as each of its members, since a group reads nothing: one row for each, so that one member dismissing it dismisses it for nobody else. A service account holding the role is told as itself, since its token reads GET /api/v1/me as a user's does. Where that reached nobody before the act, no owner on the record and nobody holding the role, or only a group with no members, every administrator is told as well, suspended ones included, since each may be the one who comes back to read it: an act that makes an owner of a namespace nobody owned, the administrator themselves among others, is not told only to the owner it made. An administrator's act goes untold only where they are the one owner there.
It is written in the transaction of the act, so that no act commits untold, and before the audit entry that records it, which is the last statement of the transaction.
func (*NS) Tree ¶
Tree reads the tree of one version and nothing else, for a namespaced caller: the API starting a run, whose inputs are bound against schemas that may name files of it.
func (*NS) TreeVersions ¶ added in v0.4.0
func (n *NS) TreeVersions(ctx context.Context, workflow, from string, limit int) ([]Listed, string, error)
TreeVersions reads up to limit versions a tree push recorded, newest first, from the one at from where it is given, and the commit of the one after them where there is one: the history of a workflow no git push has filled. ErrNoVersion where from is no such version.
func (*NS) Undeclare ¶
Undeclare removes one declaration, or answers ErrNoDeclaration where there was none.
func (*NS) Unwritten ¶ added in v0.3.0
Unwritten gives back room held for an object whose bytes never arrived.
func (*NS) UpdateRefs ¶ added in v0.4.0
func (n *NS) UpdateRefs(ctx context.Context, workflow, by string, at time.Time, updates []RefUpdate) error
UpdateRefs moves the refs of one push, all of them or none, as by at at, now where at is zero.
Each ref moves by compare and swap on what git says it names, under a lock on the workflow's row that serialises every push to the repository and the repack's swap of its packs: an update moves a ref still naming Old, a creation takes an unborn branch or a name no ref holds, and a deletion removes a ref still naming Old. Any ref no longer where the push found it fails the whole set with ErrStaleRef naming it, and nothing of the set is kept, even where the caller's transaction goes on and commits: the set is written under a savepoint of its own. That is git's atomic push, which every push is, so that a push is accepted or refused whole.
A push deleting the default branch is refused whole with ErrDefaultBranch, as git refuses to delete the branch a repository has checked out: HEAD would name nothing, and unborn would no longer mean what the wire says it means, a default branch nothing was pushed to yet, which a run naming no ref reads to run the latest version sent as a tree. Another branch is named the default first.
The lock is FOR NO KEY UPDATE, which two pushes take in turn and which leaves alone the key share a version, a grant or a run takes on the workflow's row as it is written: a push waits for a push, and nothing else waits for one.
func (*NS) Uploading ¶ added in v0.3.0
Uploading holds an object back from the collector while it is written, in every namespace, with max_artifact_bytes or without: the caller reads its bytes once this has committed.
A runner writes an object before the controller hears of the result that references it, and the object may be one whose count reached zero a day before: the collector would take it from under the write, and nothing could write the bytes again. So the write is recorded as a row of artifact_uploads counting no byte against any quota, which the collector passes by, and the object's row is held while it is, so that a collector deleting the object's bytes at that moment finishes first and the write comes after it. The row lasts the grace past until, the policy or the URL's expiry, as a count at zero keeps an object for the grace: a result heard as late as that, after an outage of the controller past the task's deadline, still finds its bytes, and an object is collected only once nothing, a reference or a write, has held it for the grace. Package db's purge.go sets out the rest.
func (*NS) VariablesFor ¶ added in v0.6.0
VariablesFor are the variables the namespace shows a workflow, by name, each value as it was written, every number a json.Number: those every workflow reads, and those that name it. Never nil, so that a caller handing them on is told apart from one that read none.
By the workflow's name, as a selected variable names it, whether or not the namespace holds a workflow of that name: a name no workflow holds yet is read by the workflow created under it.
func (*NS) VersionsAt ¶ added in v0.4.0
func (n *NS) VersionsAt(ctx context.Context, workflow string, commits []string) (map[string]Listed, error)
VersionsAt reads, of the commits given, those that are versions of the workflow, by commit.
func (*NS) WorkflowRecord ¶ added in v0.4.0
WorkflowRecord reads one workflow's repository, or ErrNoWorkflow.
func (*NS) WriteArtifact ¶
WriteArtifact records one reference and the object behind it.
The object row is what the count is on, the artifact row is the reference, and the two move together: a new reference raises the count by one, and only a reference that is genuinely new does. Writing the same reference twice is therefore not an error and not a second count, which is what lets a retried task and a replay both write what they always wrote. The same URI naming different bytes is an error, because that is a URI that stopped meaning one thing.
func (*NS) WriteHookCertificate ¶ added in v0.5.0
func (n *NS) WriteHookCertificate(ctx context.Context, workflow, path, method, by string, sum []byte) error
WriteHookCertificate replaces the certificate the webhook of workflow at path and method accepts with the one whose SHA-256 is sum. The secret written beside it, if any, stays.
func (*NS) WriteHookSecret ¶ added in v0.5.0
func (n *NS) WriteHookSecret(ctx context.Context, workflow, path, method, by string, seal func(version int) (json.RawMessage, error)) error
WriteHookSecret replaces the secret of the webhook of workflow at path and method with the one seal answers, sealed at the next write of it, and says who wrote it. The certificate written beside it, if any, stays.
func (*NS) WriteSealed ¶
func (n *NS) WriteSealed(ctx context.Context, name string, seal func(version int) (SealedValue, error)) error
WriteSealed replaces the value the namespace keeps under a name with the one seal answers, at the next version of that name.
The version is allocated here and handed to seal, rather than chosen by the caller, since it is bound into what seal produces and has to be the one the row is written at. The row is locked from the moment the version is read until the transaction ends, so two writes of one name take their turns and each is sealed at a version of its own.
type NameHeld ¶ added in v0.6.0
type NameHeld struct {
Name string
// Login is set where a user holds it; otherwise Namespace is the namespace holding it, and
// Former says it holds it as a former name.
Login bool
Namespace string
Former bool
}
NameHeld is a name a namespace cannot be given, saying who holds it: a user, as their login; a namespace, as its name; or a namespace, as a name it held before it was renamed.
type Namespace ¶ added in v0.3.0
type Namespace struct {
Name string
Kind string
// Owner is the principal it is reported to when an administrator grants themselves access,
// and empty where nobody owns it yet, as nobody owns a namespace v0.2 made.
Owner string
Quotas Quotas
CreatedAt time.Time
// Storage is the name it was created with, which its objects and sealed values are kept
// under, and FormerNames the names it held before a rename, in the order it left them.
Storage string
FormerNames []string
// AvatarUpdatedAt is when its picture was set, and zero where it has none.
AvatarUpdatedAt time.Time
}
Namespace is a namespace as an administrator creates it and the API lists it.
type NamespaceHolds ¶ added in v0.2.1
type NamespaceHolds struct {
Name string
Workflows, Runs, Secrets int
// Objects are the stored objects its runs wrote, which outlive the runs until they are
// collected, and ServiceAccounts its service accounts besides its built-in identity, whose
// tokens a script somewhere still presents.
Objects, ServiceAccounts int
// Other is a table still referring to it where none of those counted does.
Other string
}
NamespaceHolds is a namespace refused removal for what it still holds. A namespace is removed only once it is empty, because what it holds is somebody's work, and removing it would be removing that too.
func (*NamespaceHolds) Error ¶ added in v0.2.1
func (h *NamespaceHolds) Error() string
func (*NamespaceHolds) Held ¶ added in v0.2.1
func (h *NamespaceHolds) Held() string
Held says what the namespace holds, in a sentence a person reads.
type NewRun ¶
type NewRun struct {
ID agk.RunID
Workflow string
Commit string
// Trigger is what started it, and TriggeredBy who asked for it, where somebody did. A run
// of a kind nobody asks for, a schedule, a webhook or an event (agk.TriggerKind.Unattended),
// is attributed to its namespace's built-in identity, NS/agentiik, which CreateRun writes: a
// trigger creating one leaves TriggeredBy empty, and one naming anybody else is refused.
Trigger agk.TriggerKind
TriggeredBy string
// Inputs are the workflow's declared inputs as they were bound, "already held to their
// declared schemas with required and default applied", which is package schema's work
// and happens before a run exists: the API binds them against the version's declaration
// and writes what was bound, defaults included. A JSON object. Empty is none.
Inputs json.RawMessage
// Steps are every step of the graph, so that a step nobody has reached is a pending row
// rather than a missing one. The evaluator seeds its own state the same way and for the
// same reason: "the reduction to a run verdict can tell the two apart".
Steps []agk.Step
// ReplayOf is the run this one replays, and ReplayFrom the step it replays from, empty for
// a replay from the start: the steps above it are reused rather than run.
ReplayOf agk.RunID
ReplayFrom agk.Step
// Context is what fired the run, frozen on it, and empty where nothing did.
Context TriggerContext
// NamespaceVars are the namespace's variables the run reads, frozen on it: those shown to its
// workflow whose names its file does not write, read in the transaction that creates it, or
// for a replay those the run it replays read. Empty is none, and is written as nothing.
NamespaceVars map[string]any
// Caller is the step whose call started the run, for a run of trigger kind workflow, and
// Depth how deep in a chain of calls it is: its caller's, and one.
Caller *Caller
Depth int
}
NewRun is a run as it is created, before anything has decided anything about it.
type NoRoom ¶ added in v0.3.0
type NoRoom struct {
Namespace string
Limit int64
// Held is what the namespace holds, its live artifacts and its uploads, and Asked the most
// the object refused may be, which is negative for one of no stated length.
Held, Asked int64
}
NoRoom is an object refused because its namespace holds too much of its max_artifact_bytes for it to fit.
type NoRoomToMove ¶ added in v0.4.0
type NoRoomToMove struct {
Held, Moving, Limit int64
}
NoRoomToMove is a move whose target's max_artifact_bytes cannot hold the live artifacts that move, beside what it holds.
func (*NoRoomToMove) Error ¶ added in v0.4.0
func (e *NoRoomToMove) Error() string
type Notification ¶ added in v0.3.0
type Notification struct {
ID string
Recipient string
Kind string
// At is when it happened, from which the 90 days it is kept are counted.
At time.Time
// Namespace, Grant, Act and By are where an administrator widened access, the grant as
// Widening keeps it, what they did and who they are, on AdminAccessWidened alone.
Namespace string
Grant *access.Grant
Act string
By string
// Credential is the passkey whose assertion was refused, by its credential ID, on
// PasskeyCounterRefused alone.
Credential string
// Login is the administrator the break-glass path issued a recovery code, on
// BreakGlassRecovery, and the user put in a group, on AdminAccessWidened by ActJoinedGroup,
// named rather than referred to, so that removing the account leaves what the others were told.
Login string
}
Notification is one thing told to one principal.
type Object ¶
type Object struct {
Namespace string
// Digest is the bare hexadecimal, and Key is what the store is asked for.
Digest string
Key string
Size int64
}
Object is one object a sweep has claimed, for the caller to delete from the store.
type Occupancy ¶
type Occupancy struct {
Runner string
Pool string
// Slots is the concurrency it last reported at a heartbeat.
Slots int64
// Ready says it takes new work: the installation has neither drained nor revoked it, and it
// last said ready rather than draining or unhealthy. A runner that is not still finishes what
// it holds, so its tasks are counted all the same.
Ready bool
// Held is the dispatches bound to it by a redemption and not yet ended.
Held int
}
Occupancy is one runner as the metrics read it: how many tasks it said it runs at once, whether it takes new work, and how many dispatches bound to it are in flight.
type Orphan ¶ added in v0.3.0
type Orphan struct {
// Digest is the bare hexadecimal its key ends with.
Digest string
Size int64
}
Orphan is a file of the store that no row names.
type Output ¶
Output is one workflow output of a run: the step port it is a view of, and the envelope that port published.
type Pack ¶ added in v0.4.0
type Pack struct {
// Name is the pack's checksum, 40 hexadecimal digits: the SHA-1 its trailer and its index hold,
// and what its keys are made of.
Name string
// Size is the pack's length in bytes, and Objects how many objects it holds.
Size int64
Objects int
CreatedAt time.Time
}
Pack is one packfile of a repository, named by its checksum.
type Percentiles ¶ added in v0.6.0
Percentiles are three percentiles of a length of time, in whole milliseconds, and Taken is false where there was nothing to take them over.
type PinMoved ¶ added in v0.4.0
PinMoved is a pin RecordImages created or moved: Was is the digest it named before, and empty for a pin it created.
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool is the connection pool, and nothing a statement can be issued on.
It has no Query, no Exec and no Row. The only thing it hands out is a handle that has already bound a namespace, or a handle whose name says why it has not. That is the whole of how "every query path carries the namespace" is made true here: not by asking callers to remember, but by giving them nothing to forget with.
func Open ¶
Open connects, and refuses a connection that would make the policy decorative.
The check is not ceremony. Row level security is skipped entirely for a superuser and for a role holding BYPASSRLS, so an installation that connected as one would enforce the namespace nowhere while every test still passed: the tests bind a namespace, and the thing being tested is what happens when somebody does not. Refusing at startup is the only moment this can be caught before it matters.
func (*Pool) AskMove ¶ added in v0.4.0
func (p *Pool) AskMove(ctx context.Context, namespace, workflow, target, by string, at time.Time, change Change) error
AskMove judges a move of a workflow to target and, where it may be made, holds its name there and freezes it until the controller carries it out. change, where it is not nil, is made first, and is undone with everything else where the move is refused.
In one transaction on the installation, since it reads both namespaces: the workflow's row under the lock every writer of its repository takes, then the name in the target under the lock every creation of a name takes. It is refused, in this order: ChangeRefused; ErrNoWorkflow; ErrWorkflowMoving where a move of it was asked already; ErrNoNamespace where the target does not exist; ErrRunsGoing while a run of it has not finished; SharedOutputs where one of its runs and a run of another workflow share outputs a cache hit republished; ErrWorkflowExists or ErrWorkflowPurging where the target holds the name; NoRoomToMove where the target's max_artifact_bytes cannot hold its live artifacts beside those of the moves asked to it before; and *HookTaken where a webhook it has armed answers a path and a method a workflow of the target has armed, since the triggers go with the workflow and one pair answers one trigger there.
Its cache entries go at once, which it could not be refused for: a cache is what it costs to make an output again, and an entry another workflow's run found while this one waits would be outputs shared across the move.
func (*Pool) AuditTrail ¶
func (p *Pool) AuditTrail() AuditTrail
AuditTrail is this pool's audit log, for the export.
func (*Pool) BeginTerm ¶
BeginTerm raises the acquisition counter and answers the term that starts.
It is called once, by whoever has just taken the advisory lock, and never by a standby. The counter is a column and not the lock's own, because PostgreSQL does not hand one out for an advisory lock.
func (*Pool) Collectable ¶
Collectable claims objects nothing references any more.
Claimed and not deleted: the caller deletes the keys from the store through Collecting and then calls Collected. An object referenced again between the claim and the deletion is not lost, because the writer that referenced it was told to write the bytes again. An object a write is under way for, or that a live artifact names, is not claimed at all.
grace is how long an object must have sat at a count of zero. Zero means DefaultGrace; a negative one is refused, since collecting an object before it was ever collectable is not a setting anybody wants and is far too easy to write by accident.
func (*Pool) CollectablePacks ¶ added in v0.4.0
func (p *Pool) CollectablePacks(ctx context.Context, grace time.Duration, batch int) ([]RepositoryPack, error)
CollectablePacks claims up to batch packs past the grace, receiving ones a push never made live and superseded ones a repack replaced, and answers them for the store to delete their files. A pack a pass claimed and did not finish with is claimed again, whatever its age, since its files may be half deleted. grace is DefaultGrace where zero, and refused where negative, for the reason Collectable refuses one.
func (*Pool) Collected ¶
Collected removes the rows of objects whose bytes are gone.
An object referenced again since the claim is left alone, which is why the count is checked here and not only when it was claimed: the row is the only thing that knows the object was wanted after all, and deleting it would leave bytes nothing can name. So is one a writer holds at that moment, rather than waited for: the writer may be waiting on another row this holds, and the row it leaves is claimed again and removed by the next sweep. It answers how many rows it removed, so a caller can see when the two numbers differ.
func (*Pool) Collecting ¶ added in v0.3.0
func (p *Pool) Collecting(ctx context.Context, claimed []Object, remove func(context.Context, Object) error) ([]Object, error)
Collecting hands remove each object Collectable claimed whose bytes may go, and answers those remove deleted, for Collected to confirm.
Each is handed over under a lock on its row, taken before anything else is asked and held until every one is deleted: an object a writer has referenced since the claim, or one a write is under way for, is passed by, and a write of one that is held waits until its bytes are gone and writes them afresh. Whether a write is under way is asked in a statement of its own once the rows are held, since a write that recorded itself after the first statement began would be invisible to it. An object remove could not delete is left claimed for the next sweep, and said in the error, with the others deleted all the same.
remove must answer nil for bytes that are already gone, which a sweep that died after deleting them and before confirming leaves.
func (*Pool) CompleteMove ¶ added in v0.4.0
func (p *Pool) CompleteMove(ctx context.Context, m Move, copied MoveObjects, grace time.Duration) (Moved, error)
CompleteMove carries a move out, in one transaction on the installation: what the workflow's rows count is counted under the target and let go under the source, digest by digest; the workflow's row changes namespace, and every key naming it, its versions, refs, runs, grants, pins, manifests, packs and all a run holds follows (0053, 0057); its logs' keys are rewritten under the target; what the move leaves under the source's keys, logs and packs, is kept for grace and then deleted; the expiry of its runs and artifacts is brought within the target's max_retention_days; and the move is recorded as workflow.update in both namespaces, as the one who asked for it.
The objects are copied under the target's keys before it, those ObjectsOf read as copied, and it is Done false, having changed nothing, while the move is not ready or no longer asked, and where a chunk of its logs was indexed since copied was read, which the next pass copies.
The logs of the workflow's runs and its live artifacts are held first, in that order, which is the order a shipment holds a log and then its task in: a shipment writing a chunk finishes before the move reads what it counts and rewrites, and one after it waits for the move and is then refused, its runner shipping it again under the target's keys; and a fetch that would spend an artifact's last fetch cannot retire it between the move counting it and letting it go.
func (*Pool) Current ¶ added in v0.6.0
Current refuses a database that lacks a migration this binary carries, naming the first it lacks. Every query the programs make is written against the schema their migrations leave, so a program started on an older one serves, and fails on whatever reaches what a missing migration changed, as a 500 that says nothing of the schema. It reads schema_migrations through the pool's own role, which may read it and nothing more of it.
func (*Pool) CurrentName ¶ added in v0.6.0
CurrentName is Wide.CurrentName for a caller holding no transaction, the router resolving the namespace an address names among them. The namespaces are the installation's and under no policy, so it is asked through a handle on the name asked about rather than through the installation's door, which would need a reason for what every request asks.
func (*Pool) ExpireArtifacts ¶
ExpireArtifacts retires every reference whose duration has run out, batch at a time, and answers how many it retired.
It retires the reference and lowers the count behind it, and it deletes nothing: "Expiry applies to the reference, never to the object." A run that loses an artifact is marked replayable from the start only in the same transaction, because the two facts are one fact and a reader that saw one without the other would offer a replay that cannot run.
It waits on nothing. A decision holds its run's row and then the objects it counts, and writes its artifacts again after them, so a purge that held an artifact and then waited for the run or the object would be waiting on a decision waiting on it. So the runs, then the references, then the objects are taken only where nobody holds them, and a reference whose run or object is held is left for the next pass, which is at most one decision away.
func (*Pool) ExpiredLogs ¶
ExpiredLogs claims the logs of runs whose retention has run out.
A log is a URI and not a digest: one task wrote it, nothing else names it, and there is nothing to count. So it is claim, delete, confirm, with LogsPurged as the confirmation, and the line count and the truncation flag stay behind as the record that there was a log.
The keys are every object recorded for the log, those a failed write left behind included, and batch bounds them as it bounds the logs, since one log may be written in thousands of chunks: a log with more is handed over again, the rest of it, at the next claim. A task whose log is being written to is skipped, since its row is held until the chunk and its key are recorded, and is claimed on a later pass: claimed now, the object being written would be written after the claim and named by nothing the purge still holds. A shipment arriving once the run's retention has run out is refused, so a log claimed is one nothing is added to.
func (*Pool) In ¶
In runs fn inside one transaction, in one namespace.
The namespace is bound with SET LOCAL, so it lasts exactly as long as the transaction and cannot leak into the next caller of a pooled connection. fn returning an error rolls back; fn returning nil commits.
func (*Pool) Installation ¶
func (p *Pool) Installation(ctx context.Context, reason Reason, fn func(context.Context, *Wide) error) error
Installation runs fn across every namespace, for a named reason.
func (*Pool) LiveEnvelopes ¶ added in v0.3.0
LiveEnvelopes answers the envelopes the runs of namespace that have not finished reference, published and per shard, the bare hexadecimal of each once: the files they name are the ones those runs are working with, which a shard's envelope names before any artifact does, and which a run v0.2 began names until a decision of this release records them.
func (*Pool) LogsGone ¶ added in v0.3.0
LogsGone stamps runs whose retention has run out and none of whose tasks holds a log any more, batch runs at a time, so that ExpiredLogs looks no further at them, and answers how many it stamped.
A run is stamped once nothing can give one of its tasks a log again. A shipment asks the run's retention once it holds its task, so the tasks of the runs are held here, waiting for any shipment already under way, and whether a task holds a log is asked only then, in a statement of its own: a shipment that got in first has named its log by then, and one that comes after finds the retention run out and writes nothing.
func (*Pool) LogsPurged ¶
LogsPurged records that the objects of those logs are gone from the store, and answers how many of the logs are now gone whole.
It forgets the keys it was handed and the chunks they held, and nothing else, so an object recorded after the claim is still there for the next one. A log none of whose objects is left has its URI taken off its task; where each log stood stays: how many lines it held and whether the cap cut it short.
func (*Pool) MovedObjectsDue ¶ added in v0.4.0
MovedObjectsDue reads at most batch of the keys moves left whose grace has passed, the longest waiting first.
func (*Pool) MovedObjectsGone ¶ added in v0.4.0
func (p *Pool) MovedObjectsGone(ctx context.Context, gone []MovedObject) error
MovedObjectsGone forgets keys whose objects were deleted.
func (*Pool) Moves ¶ added in v0.4.0
Moves reads the moves asked and not yet carried out, the oldest first, at most batch of them.
func (*Pool) ObjectsOf ¶ added in v0.4.0
ObjectsOf reads what a move copies: every object a version of the workflow names in its tree, an envelope a run whose envelopes are kept names in its document or a grant of it counted, and a live artifact names; every key a log of its runs is written under; every pack of its repository live or superseded. It is read before the copying and counted again when the move is carried out, so what it names is at least what the move counts.
func (*Pool) Orphaned ¶ added in v0.3.0
Orphaned hands orphans of namespace to the collection, each as a row of artifact_objects that counts nothing and is collectable from now, and answers how many it handed over.
Each is asked again what Unnamed asked, in the statement that writes its row, and one that something holds now is passed by: a write that began since, a reference recorded since, a run of the namespace found to be waiting for its files to be recorded.
func (*Pool) PacksCollected ¶ added in v0.4.0
PacksCollected forgets the packs CollectablePacks claimed whose files the store has deleted, and answers how many it forgot.
func (*Pool) PurgeDeleted ¶ added in v0.4.0
PurgeDeleted takes the deleted workflows a step further, each part up to batch rows in a transaction of its own, and answers what it removed and whether any part was full:
- a run of one that finished since the deletion has its expiry, and its artifacts', brought to now, as the deletion brought those of the runs that had finished;
- a run whose envelopes and logs the purges have let go of, and none of whose artifacts is live, is deleted, its steps, tasks, grants and notifications with it;
- once none of its runs is left, each version lets go of the objects its tree named, as a run's envelopes do at their expiry, and is deleted;
- its packs are superseded, which the collection deletes the grace after, as it does a repack's, so that a fetch that began before the deletion reads on;
- and once nothing names it, the workflow's row is deleted, its refs, grants, pins and manifests with it, and its name is free.
func (*Pool) PurgeEnvelopes ¶
PurgeEnvelopes drops the envelopes of runs whose retention has run out, batch runs at a time, and answers how many runs it dropped them of.
A run's envelopes are what its decision document references, published and per shard alike, and what each of its tasks was handed on its input ports, once per grant, because all of them are objects the controller put in the store and an object nothing counts is an object the collector never sees. What goes is the count on them, which is what eventually lets the bytes be collected. What stays is the record: the digests in steps.ports are the record of what was published, and the chapter keeps only digests and URIs in the database anyway.
The run's row is taken before anything is lowered and stamped in the same transaction, which is what keeps a sweep from taking the same run for ever and two sweeps at once from lowering its counts twice: migration 0038 says why the stamp is on the run. A run whose steps were all stamped before it had one of its own is stamped and lowers nothing. The counts of the whole batch are lowered in one statement, so that a run fanned out to ten thousand shards costs one statement and not twenty thousand, held inside one transaction.
func (*Pool) PurgeUploads ¶ added in v0.3.0
PurgeUploads forgets writes that have lapsed, batch at a time, and answers how many.
A write holds its rows from before its bytes are read: the room it was made, until a quarter of an hour after the policy it was written with, and its hold on the object, until the grace after it. Past that a row holds nothing back and counts nothing, and a namespace with no max_artifact_bytes never counts its uploads again, so nothing but this lets them go.
func (*Pool) RecordUnrecorded ¶ added in v0.3.0
RecordUnrecorded records the files of each run as its artifacts, expiring its namespace's max_retention_days after it finished, or kept for ever where it sets none, and sets the run's files_recorded, all in one transaction. A run given no expiry, as one a v0.2 controller finished after migration 0038 is, is given the same, for its envelopes and logs.
A file is recorded under the URI its envelope names, as a decision records it, where that URI is of the run itself and of one of its steps: a file of another run is recorded, if at all, by that run's own publication, and dated by that run's end. A reference already there is left as it was, with its own expiry and its count, which is how an output v0.2 gave a retain keeps what it was given, and a run recorded twice is counted once.
An object is counted up by the references written, under a lock on its row, as a decision counts it. It waits on nothing it can pass by: a run another call is recording is passed by, and so is a file whose object a writer holds at that moment, its run being left waiting, whole, for a later call; a decision holds its objects while it writes its artifacts, and a recording that waited for it could wait on a decision waiting on it. What it cannot pass by, a writer creating an object's row as this does, it waits for recordingWaits at the most, and leaves the whole batch for a later call past it. A file whose object is being collected is not recorded, since its bytes may be gone by now, nor one whose size is not its object's: a reference that named no bytes would be answered as an artifact nobody can fetch.
func (*Pool) Repackable ¶ added in v0.4.0
Repackable answers up to batch workflows whose repositories hold more than most live packs, the ones holding most first.
func (*Pool) Session ¶
Session is one connection, pinned, for as long as fn runs.
The advisory lock the controller is elected by is held "until explicitly released or the session ends", and LISTEN is a property of a connection: both outlive a transaction and neither survives a connection going back to the pool. Nothing namespaced is reachable through it, because a session held for minutes is not a place to be reading a tenant's rows from.
func (*Pool) Storage ¶ added in v0.6.0
Storage is the storage name of the namespace named name, as NS.Storage answers it, for a caller that holds no handle on it.
func (*Pool) Sweepable ¶ added in v0.3.0
Sweepable answers the namespaces whose objects an orphan sweep may walk, in name order: every namespace but those with a finished run whose artifact files are still to be recorded.
func (*Pool) Unnamed ¶ added in v0.3.0
Unnamed answers which of digests, bare hexadecimal digests of objects of namespace, nothing in the database holds: no row counts it, no live artifact names it and no write holds it, in a namespace with no finished run whose files are still to be recorded.
It is the look before the envelopes are read, which only a few files ever need, and decides nothing: Orphaned asks all of it again as it writes.
func (*Pool) UnrecordedRuns ¶ added in v0.3.0
func (p *Pool) UnrecordedRuns(ctx context.Context, after Unrecorded, batch int) ([]Unrecorded, error)
UnrecordedRuns answers at most batch runs whose artifact files are still to be recorded, those after the run of after's namespace and identifier in that order, from the first where after's namespace is empty, with the envelopes they keep: those their decision references, published and per shard, and those their steps published, each once.
A caller goes on from the last run it was answered rather than from the first left, so that a run another caller is recording at that moment, or one whose objects a writer held, is passed by and never read again in a loop.
func (*Pool) WatchLive ¶ added in v0.6.0
func (p *Pool) WatchLive(ctx context.Context, on func(LiveChange)) error
WatchLive calls on with every change said on LiveChannel, and with ChangedAll once listening. It blocks until ctx is done, or the connection it listens on fails, and answers why.
It takes a session of its own, since LISTEN is a property of a connection. A payload it cannot read is said as ChangedAll rather than dropped, since what it meant is then read again whatever it was.
func (*Pool) WatchLogs ¶
WatchLogs calls on with the key of every log a shipment moved on, and with the empty key on every sweep. It blocks until ctx is done, or the connection it listens on fails, and answers why.
It takes a session of its own, since LISTEN is a property of a connection. The first thing it does once listening is sweep: whatever was shipped before it listened is a notification it did not hear, and the sweep is what makes that cost latency rather than lines. Then it sweeps every sweep, which is also what tells a reader of what no shipment announces, a task that ended or a step that reached its verdict. Every sweep and not every sweep without a notification: on an installation where some task ships something every few seconds, a quiet spell would never come, and a reader whose step ended would never hear it.
type PoolSeries ¶ added in v0.6.0
type PoolSeries struct {
Pool string
Buckets []SlotBucket
Runners []RunnerSeries
}
PoolSeries is one pool's slots, its runners' together, bucket by bucket, and each runner's.
type Profile ¶ added in v0.6.0
type Profile struct {
GivenName string
FamilyName string
Title string
Location string
Timezone string
Bio string
}
Profile is what a user says of themself, each field empty where it is left unsaid: their given and family names, which their display name is made of, what they do, where they are, the IANA time zone they work in, and a line about themself.
type QuotaBucket ¶ added in v0.6.0
type QuotaBucket struct {
// RunsCreated are the runs created in the bucket, against max_runs_per_hour, and RunsRefused
// those refused for it, whatever asked for them: see migration 0064.
RunsCreated, RunsRefused int
// TasksInFlightMax is the most tasks on their way to a runner or at one and not yet ended at
// once in the bucket, which is what max_concurrent_tasks counts.
TasksInFlightMax int
// ArtifactBytes is what max_artifact_bytes counted at the bucket's end: the bytes of the live
// artifacts, each digest once. ArtifactBytesAdded is the bytes of the artifacts written in the
// bucket, each digest once.
ArtifactBytes, ArtifactBytesAdded int64
}
QuotaBucket is what a namespace asked of its quotas in one bucket.
type Quotas ¶ added in v0.3.0
type Quotas struct {
// MaxConcurrentTasks is always set, at 20 unless an administrator set it otherwise.
MaxConcurrentTasks int
// MaxRetentionDays bounds how long the namespace keeps what its runs produce, and nothing
// where it is zero: an installation keeps what it ran until somebody decides otherwise.
MaxRetentionDays int
// The others bound nothing where they are zero, or nil for AllowedRunnerPools, which then
// allows every pool that accepts the namespace. MaxRunDuration is written on a timeout's
// grammar, 4h, as the administrator wrote it.
MaxRunsPerHour int
MaxArtifactBytes int64
MaxRunDuration string
AllowedRunnerPools []string
}
Quotas are what one namespace may consume.
type Reason ¶
type Reason string
Reason is why a piece of work legitimately has no namespace.
It is an enumeration and not a string so that the set stays small and countable: every escape from the namespace rule is one of these, a test counts the call sites, and adding a new one is a line somebody writes here and a reviewer reads.
const ( // ControllerSweep is the controller looking for actionable work across the // installation, which the documentation calls the correctness guarantee of the // scheduler, the notification being only a latency optimisation. It is also what the // controller reads before it lets a run in, since "authorisation is re-evaluated when a // run is created": the principal the run is attributed to, its groups and its grants in // the run's namespace, the bootstrap state, and the grants revoked from it, which only the // audit log still holds. ControllerSweep Reason = "the controller's sweep" // Purge is one of the three sweeps, over envelopes, artifacts or logs, each // against its declared retention, and the recording of the artifact files a v0.2 // controller left unrecorded, which gives the artifact purge its dates: a run is // finished in whichever namespace, and so is the recording. Purge Reason = "a retention purge" // Collect is the garbage collector, over objects whose reference count reached // zero, and over the packs of workflow repositories: those a repack superseded or a push // never made live, and the repositories due a repack. Collect Reason = "collecting objects nothing references" // RunnerInventory is the runner table, which belongs to the installation: a // runner serves several namespaces and its inventory is administrator only. RunnerInventory Reason = "the runner inventory" // InstallationActivity is what every namespace together is doing, counted for an administrator: // the runs created and the tasks in flight, bucket by bucket, and what runs now, as counts that // name no run, workflow or namespace. An administrator holds no run:read by being one, so no // namespace's handle would let it count anything, and what is counted is the installation's // load, which is theirs to watch as the runners are. InstallationActivity Reason = "the installation's activity, counted for an administrator" // Heartbeat is one request covering every in-flight task on one host, which is // one host across however many namespaces it is working for. Heartbeat Reason = "a runner's heartbeat" // Redemption is a runner turning a grant into what the task it names was given. // The namespace is what the grant answers rather than what the caller claims: a // runner works for several and knows which one this task belongs to only because // the grant said so, and a request that carried a namespace of its own would be a // request choosing the scope its own credential is checked in. What it reads is the // grant, the task it names, and the tree of the one version the grant's scope names. Redemption Reason = "a grant redemption" // LogShipment is a runner shipping a chunk of a task's log, which it is authorised for // the way it redeems: by the task's grant, whose namespace is found from the grant and // never taken from the request, and by the task being bound to it. What it reads and // writes is the grant, the task it names, and the index to that task's log. LogShipment Reason = "a runner shipping a task's log" // RunRoute is a route about one run, whose path names the run and not the workflow it is // of, and often not its namespace: "Agentiik sends the push service an identifier and a // state", and the application a notification opens holds that identifier and nothing // else. What it reads is which namespace and workflow the run is of, and that goes to the // router and the authorizer and nowhere else; the route itself reads and writes through // In, in the namespace it was authorised in. RunRoute Reason = "a route that names a run and not its namespace" // RunListing is GET /api/v1/runs, "across every namespace the caller can read", and GET // /api/v1/{ns}/runs, the same listing within one, and GET /api/v1/{ns}/stats/runs, // /stats/steps and /stats/ports, which count what that listing lists, since "an aggregate // over runs discloses the runs", and GET /api/v1/{ns}/workflows, the workflows whose runs it // lists, each with its newest. What it reads is which workflows there are, for the // authorizer to be asked about each, and then the runs of the ones it allowed and of no // others: the namespaces a listing reaches are the ones the authorisation decision named, as // In's always are. One namespace's listing steps past In too, rather than reading its runs // under the namespace's policy, because that policy admits every workflow of the namespace, // and "a deny wins at any scope" only where the workflow is in the question. RunListing Reason = "a listing of runs across the namespaces its caller can read" // AuditLog is the audit log read across the installation, by the export, by a verification and // by an administrator reading it: "separate and append-only", one chain holding the acts of // every namespace and of the installation itself, which no namespace's handle could read whole. AuditLog Reason = "the audit log, one chain across the installation" // NamespaceAdministration is a namespace created, removed, renamed, given a picture or given // its quotas through the API, or created or removed by agentiik-api namespace on the server. A // namespace is the scope every other handle is opened in, so creating one is not something a // handle on one can do, removing one reads whether any of its rows remain, renaming one writes // every row naming it and those of other namespaces naming it or its service accounts, and a // listing of them spans the installation. NamespaceAdministration Reason = "a namespace created, removed or given its quotas" // Identity is who a request is from, and the records that say so: the principals, their // credentials, tokens, sessions and enrolment codes, the challenges of the passkey ceremonies // and the TOTP generators waiting for their first code, the authentication policy and the // bootstrap state. A token, a session or a passkey names its principal before any namespace is // in question, and administering them is the installation's business rather than a namespace's. A user's first sign-in creates their personal namespace // in the same transaction, so that no session opens without it and none is made for a sign-in // that failed. A grant is written through it too, since whether an administrator can still // sign in once a role it gives applies is read from their grants in every namespace, in the // transaction that writes it. Identity Reason = "who a request is from, and the principals and credentials that say so" // Authorisation is what one principal holds across the namespaces: the grants of a principal // and its groups wherever they are, for a listing that spans every namespace its caller can // read. A decision about one namespace reads that namespace's grants through In. Authorisation Reason = "the grants one principal holds across the namespaces" // WorkflowMove is a workflow moved from one namespace to another, which no handle on one of // them can do: the move is asked in the source, holds its name in the target, and is carried // out by the controller that leads, which re-keys the workflow's rows from the one to the // other and counts its objects in the target as it lets them go in the source. WorkflowMove Reason = "a workflow moved from one namespace to another" // EventDelivery is an event published into one namespace and heard in the others that name // it: "only events published into the workflow's own namespace, or into the one namespace // names where it granted the workflow's namespace read access". What it reads is the event // triggers armed across the installation that hear the namespace published into, for the // authorizer to be asked about each namespace they are armed in; what it writes, the runs // they start, the firings recorded on them and the event remembered, it writes through // Within, in the namespace each belongs to. EventDelivery Reason = "an event published into one namespace, heard in those that name it" // SchemaUpgrade is the schema itself. Named for the act rather than for the file, // since Migration is the file. SchemaUpgrade Reason = "a schema upgrade" )
type Recorded ¶ added in v0.3.0
type Recorded struct {
// Runs are the runs whose files are recorded, and which are waited for no longer.
Runs int
// Artifacts are the references it wrote, a reference already there being left as it was.
Artifacts int
// Left are the runs it could not record now, since a writer held an object one of their
// files is: they are still waited for, for a later call to record.
Left int
}
Recorded is what RecordUnrecorded did.
type Recording ¶ added in v0.3.0
Recording is one run's files, as the envelopes its steps published name them, for RecordUnrecorded.
type Redeemed ¶
type Redeemed struct {
Namespace string
// Storage is the namespace's storage name, which every object it holds is kept under and its
// secrets' values are sealed under (NS.Storage): what a redemption presigns its URLs for.
Storage string
// Row is the task's own identifier, the one the grant names inside its text, and Task is
// the idempotency key that says which unit of work it is. A redemption is asked with both
// and answers the row.
Row string
Task agk.TaskID
Scope GrantScope
// ExpiresAt is the grant's own expiry, which is the task's deadline. Anything the
// redemption hands out is minted to end with it: a URL that outlived the task it was
// fetched for would be the standing credential the grant exists to avoid.
ExpiresAt time.Time
}
Redeemed is what a grant turned out to be for.
type Ref ¶ added in v0.4.0
type Ref struct {
// Name is the ref in full, refs/heads/main or refs/tags/v2.1.0.
Name string
// Commit is the commit it points at, an annotated tag peeled to it, and empty while the branch
// is unborn. Tag is the annotated tag object an annotated tag's ref names, and empty for a
// branch and a lightweight tag.
Commit string
Tag string
// Protected is whether pushing to it takes grant:manage, which only the default branch of a
// protected repository is.
Protected bool
// MovedBy and MovedAt are who last moved it and when, empty while it is unborn.
MovedBy string
MovedAt time.Time
}
Ref is one branch or tag.
type RefUnresolved ¶ added in v0.5.0
type RefUnresolved struct {
Ref string
// Ambiguous says the ref names a branch and a tag both, rather than nothing.
Ambiguous bool
}
RefUnresolved is a ref a run was asked by that names no commit to run, or two: no branch, no tag and no version of that name, or a name a branch and a tag both hold.
func (*RefUnresolved) Error ¶ added in v0.5.0
func (e *RefUnresolved) Error() string
type RefUpdate ¶ added in v0.4.0
type RefUpdate struct {
Ref string
// Old is what the pusher found the ref naming, empty where it creates it. New is what it names
// once moved, empty where it deletes it: a commit, or an annotated tag object for a tag.
Old string
New string
// Commit is the commit New peels to, where New is an annotated tag; empty is New itself, which
// is what a branch and a lightweight tag name.
Commit string
// Unprotected is that the push was judged to move the ref as a ref nobody protects, without
// asking whether the pusher holds grant:manage, so that it is moved only while that still
// holds: a protection set between the push being judged and its refs moving would otherwise
// be moved past by a pusher who never held what it asks for.
Unprotected bool
}
RefUpdate is one command of a push: git's old and new values of one ref, each 40 hexadecimal digits, and empty where git writes forty zeros.
type Reference ¶
type Reference struct {
URI agk.URI
Digest string // sixty-four lowercase hexadecimal characters, as the envelope carries it
Size int64
MediaType string
For time.Duration
Fetches int
// WithRun is a file that lives at least as long as its run keeps the envelopes naming it,
// which SaveDecision makes it once the run has finished and that is known: a file of a port
// that declares no retain of its own, published or only a shard's. An envelope kept while
// the files it names are collected would be read back naming bytes that are gone.
WithRun bool
}
Reference is one artifact, as it is written.
For and Fetches are the two mechanisms of retain, which "answer two different questions: a duration answers how long may this be fetched, and a single fetch answers may this be fetched more than once". A budget comes with a duration: "a one-shot artifact still has a duration, which is what expires it when nobody ever comes for it". Fetches is zero where the workflow declared no budget, and For is zero where it declared no retain at all, which keeps the artifact as long as the namespace allows: max_retention_days is what bounds what nobody asked for, as it bounds a run's envelopes, and an artifact with no expiry would be one no quota ever lets go of.
type RenameWaits ¶ added in v0.6.0
RenameWaits is a rename refused for what has to end first: runs of the namespace queued, running or waiting, moves of its workflows to it or from it asked and not carried out, and runners not revoked that narrow themselves to it by name on their host.
func (*RenameWaits) Error ¶ added in v0.6.0
func (e *RenameWaits) Error() string
func (*RenameWaits) Held ¶ added in v0.6.0
func (e *RenameWaits) Held() string
Held says what the rename waits for, in a sentence a person reads.
type Repository ¶ added in v0.4.0
type Repository struct {
Namespace string
Workflow string
// Key is what its packs are kept under in the object store, <namespace>/git/<key>/: random, and
// never changed, so that a rename moves no object.
Key string
// Storage is the storage name of its namespace, the first segment of every key of its packs,
// which a namespace's rename leaves as it was (NS.Storage).
Storage string
// DefaultBranch is the branch HEAD names, without refs/heads/.
DefaultBranch string
// Refs are its branches and tags, in git's order, byte by byte. The default branch is among them
// with no commit while it is unborn.
Refs []Ref
// Packs are its live packs, newest first: every object any ref names is in one of them.
Packs []Pack
}
Repository is a workflow as git reads it, at one moment.
type RepositoryPack ¶ added in v0.4.0
type RepositoryPack struct {
Namespace string
Repository string
Pack
// Storage is the storage name of its namespace, which its files are kept under (NS.Storage).
Storage string
}
RepositoryPack is one pack of one repository, named for the store: the namespace, the repository's key its files are kept under, and the pack.
type Resolved ¶
type Resolved struct {
URI agk.URI
// Digest is the sixty-four hexadecimal characters an envelope carries, and Key is
// the physical key those characters address, namespace and all.
Digest string
Key string
Size int64
MediaType string
Status Status
// ExpiresAt is when the reference stops being fetchable, and the zero time where nothing
// bounds it.
ExpiresAt time.Time
// RetiredAt is when a retired reference was retired, and the zero time on a live
// one.
RetiredAt time.Time
// Fetches is what is left of the budget, zero where there is none or none is left, and
// Budgeted says which: whether the workflow declared a fetch budget at all.
Fetches int
Budgeted bool
// Held is how many of Fetches are held for transfers being served, which none but those
// transfers may spend.
Held int
}
Resolved is what a logical URI resolves to.
type Revocation ¶ added in v0.3.0
Revocation is a grant revoked, as the audit log recorded it: the grant as it was, and when and by whom it was revoked.
type Room ¶ added in v0.3.0
type Room struct {
// contains filtered or unexported fields
}
Room is what MakeRoom held for one write, for Stored or Unwritten to settle.
type Rotated ¶
Rotated is what it gets back: a credential that exists once, and when that one stops being accepted.
type Rotating ¶
type Rotating struct {
// Credential is the one the request was authenticated with.
Credential string
// Runner is the runner the request names, which the signature is over.
Runner string
// SignedAt is the request time the runner signed, by its own clock.
SignedAt time.Time
// Signed is the message the signature is over, as the wire composes it from the runner and
// the request time, and Signature is the runner's Ed25519 signature of it.
Signed []byte
Signature []byte
}
Rotating is what a runner presents to be given a new credential: the credential it holds, and proof that it holds the key it joined with.
type RunBucket ¶ added in v0.6.0
type RunBucket struct {
// Runs are the runs created in the bucket by state: an ended run under its final state, one
// still going under where it is now, so that they add up to what GET /api/v1/runs lists over
// the bucket, within the namespace's retention. A run's record outlives its retention, which
// lets go of its envelopes and logs, and a series stops where the retention does all the same.
Runs map[string]int
// Duration is how long the runs of the bucket that ended took, from started_at to finished_at.
Duration Percentiles
// QueueWait is how long their tasks waited to be handed out, from ready_at to dispatched_at.
QueueWait Percentiles
// Retries are the attempts that were retried, by the exit code of the attempt that failed, the
// most frequent first.
Retries []ExitCodeCount
}
RunBucket is what the runs created in one bucket came to.
type RunDetail ¶
type RunDetail struct {
RunSummary
Inputs map[string]any `json:"inputs,omitempty"`
Outputs map[string]any `json:"outputs,omitempty"`
// ReplayFromStartOnly is the marker the artifact purge sets: "once any input to a step
// it could restart from is gone, the run is marked as replayable from the start only,
// and the console says so where it would otherwise offer the step".
ReplayFromStartOnly bool `json:"replay_from_start_only"`
// ReplayOf is the run this one replays, and ReplayFrom the step it replays from, left out
// for a replay from the start: the steps above it were reused rather than run, and carry a
// verdict and no task.
ReplayOf agk.RunID `json:"replay_of,omitempty"`
ReplayFrom agk.Step `json:"replay_from,omitempty"`
// EnvelopesPurged says the run's envelopes have gone with its retention, which no replay
// from a step can reuse. Not answered, since the steps' ports say so each.
EnvelopesPurged bool `json:"-"`
// Includes are the workflow includes of the version the run pinned, each with the commit its
// ref resolved to when the version was pushed: "the run records the commit it resolved to".
// Absent where it includes no other repository.
Includes []RunInclude `json:"includes,omitempty"`
// Reason is why the run ended as it did, where nothing in its workflow is what ended it, and
// empty on every other run: from v0.3.0, a run its principal no longer held workflow:run for
// when it was created, which "ends cancelled before any task, with a reason naming the grant
// that lapsed".
Reason string `json:"reason,omitempty"`
Steps []StepSummary `json:"steps"`
Tasks []TaskSummary `json:"tasks"`
// Artifacts are the files the run's steps published, live or retired: "the run detail keeps
// showing the artifact's name, size and digest with its collection recorded", so that one
// fetched past its retention is told from one that never existed.
Artifacts []ArtifactSummary `json:"artifacts"`
}
RunDetail is a run and what became of every part of it.
type RunInclude ¶ added in v0.4.0
type RunInclude struct {
Workflow string `json:"workflow"`
Ref string `json:"ref"`
Commit string `json:"commit"`
}
RunInclude is one workflow include of the version a run pinned: the repository and the ref the file wrote, and the commit the ref resolved to at the push.
type RunQuery ¶
RunQuery is how a listing is narrowed, besides the workflows it is of, which are what the authorizer allowed and are given beside it.
Since and Until bound when a run was created, both included, and the zero time bounds nothing. Included at both ends, so that a client paging back through time by passing the last run it was given as Until is given that run again rather than skipping the ones created in the same instant.
type RunSummary ¶
type RunSummary struct {
// Namespace is where the run is, which a listing across namespaces has to say and a run
// read by its identifier alone is the only place to learn.
Namespace string `json:"namespace"`
Run agk.RunID `json:"run"`
Workflow string `json:"workflow"`
Commit string `json:"commit"`
State agk.RunState `json:"state"`
// Trigger is served as trigger_kind, the name an expression reads it by.
Trigger agk.TriggerKind `json:"trigger_kind"`
TriggeredBy string `json:"triggered_by,omitempty"`
// From is the run and the step whose call started this run, for trigger_kind workflow and
// no other.
From *Caller `json:"from,omitempty"`
CreatedAt time.Time `json:"created_at"`
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
}
RunSummary is one row of a listing.
type RunTrace ¶
type RunTrace struct {
Namespace string
Run agk.RunID
Workflow string
Commit string
State agk.RunState
Trigger agk.TriggerKind
CreatedAt time.Time
StartedAt time.Time
FinishedAt time.Time
Dispatches []TracedDispatch
}
RunTrace is a run and every dispatch of its tasks.
type Runner ¶
type Runner struct {
ID string `json:"runner"`
Pool string `json:"pool"`
Labels []string `json:"labels"`
// PublicKey is the key the host joined with. It is not answered in the inventory, which
// lists hosts rather than proves them.
PublicKey ed25519.PublicKey `json:"-"`
CPU int `json:"cpu"`
MemoryBytes int64 `json:"memory_bytes"`
DiskBytes int64 `json:"disk_bytes"`
Architecture string `json:"architecture"`
AgentVersion string `json:"agent_version"`
Namespaces []string `json:"namespaces,omitempty"`
Containment *Containment `json:"containment,omitempty"`
State string `json:"state"`
DrainReason string `json:"drain_reason,omitempty"`
// Who ordered a drain and a revocation, and when, which the row keeps for the inventory
// beside the audit log's record of each order.
DrainedBy string `json:"drained_by,omitempty"`
DrainedAt time.Time `json:"drained_at,omitzero"`
RevokedBy string `json:"revoked_by,omitempty"`
RevokedAt time.Time `json:"revoked_at,omitzero"`
// ResultsAcceptedUntil is the end of a revocation's grace: the runner is answered, told to
// drain, and its results taken until then, and refused everywhere from then on. Zero for a
// runner nobody revoked.
ResultsAcceptedUntil time.Time `json:"results_accepted_until,omitzero"`
// What the runner last said of itself at a heartbeat: what it will do with new work, which
// is not State (the installation's word on it), and how many tasks it will run at once.
// Neither is written until its first heartbeat.
ReportedState string `json:"reported_state,omitempty"`
Concurrency int64 `json:"concurrency,omitempty"`
JoinedAt time.Time `json:"joined_at"`
LastSeenAt time.Time `json:"last_seen_at,omitzero"`
RotateBy time.Time `json:"rotate_by,omitzero"`
}
Runner is one host, as the inventory holds it.
type RunnerPool ¶
type RunnerPool struct {
Name string
Labels []string
// AcceptedNamespaces is whose work this pool runs. Empty is every namespace, which is
// what an installation with one pool has.
AcceptedNamespaces []string
// Ceilings are the most one task may be given here, over what it asks for rather than
// over the host.
Ceilings Ceilings
// Containment is the tier, and empty is ContainmentHardened.
Containment string
CreatedAt time.Time
CreatedBy string
}
RunnerPool is a set of hosts and the policy they carry.
func (RunnerPool) Accepts ¶
func (p RunnerPool) Accepts(namespace string) bool
Accepts says whether this pool runs that namespace's work. No list at all is every namespace.
type RunnerSeries ¶ added in v0.6.0
type RunnerSeries struct {
Runner string
Buckets []SlotBucket
Silences []RunnerSilence
}
RunnerSeries is one runner's slots, bucket by bucket, and its silences over the range.
type RunnerSilence ¶ added in v0.6.0
RunnerSilence is one silence between two heartbeats of a runner of Silence or more: from the last heartbeat before it, lasting until the next, or until the end of the range for one still going, and the tasks of the runner the sweep declared lost in it.
type RunsPerHourReached ¶ added in v0.3.0
type RunsPerHourReached struct {
Namespace string
Limit int
// RetryAfter is how long until one more run fits: until the oldest of the runs counted
// against the limit leaves the window.
RetryAfter time.Duration
}
RunsPerHourReached is a run refused at creation because its namespace has created as many runs in the last 60 minutes as its max_runs_per_hour allows.
It is for the caller to say what that comes to, since every run is created by CreateRun whatever started it and what a refusal means is not the same for each: the API answers 429 with Retry-After, and a scheduled or event firing starts no run and is recorded as a skipped firing, with Reason, rather than failing, since the trigger is not broken and fires again when it next comes round. Nothing is written before it is answered, so the transaction it is answered in may go on to record the skip.
func (*RunsPerHourReached) Error ¶ added in v0.3.0
func (r *RunsPerHourReached) Error() string
func (*RunsPerHourReached) Reason ¶ added in v0.3.0
func (r *RunsPerHourReached) Reason() string
Reason says why no run was created, in a sentence a person reads. It names the quota and not how many runs the hour holds, which is more than the quota where an administrator lowered it.
func (*RunsPerHourReached) Seconds ¶ added in v0.3.0
func (r *RunsPerHourReached) Seconds() int
Seconds is RetryAfter in whole seconds, as Retry-After writes it: rounded up, since a client asking again a fraction of a second early would find the oldest run still counted, and at least one.
type Saved ¶
type Saved struct {
// New is false where this commit was already recorded with this tree, which is the same
// version pushed again and changes nothing.
New bool
// MustWriteBytes are the digests of tree files whose objects a sweep had claimed when this
// version raised its references onto them. The references are safe either way; what is
// not safe is assuming the bytes survived a sweep that had already decided to delete them,
// so the caller writes those again. See the collection protocol in purge.go.
MustWriteBytes []string
// Recorded are the digests of tree files whose objects had no row until this version
// raised its references onto them. The reference is as safe as any other; the bytes are
// whatever the caller wrote. A caller that skipped writing one because the store said it
// held it writes it now all the same, because the sweep that collects an object whole,
// bytes and then row, leaves exactly this behind when it finishes between the store's
// answer and this version, and MustWriteBytes cannot see a row that is gone.
Recorded []string
}
Saved is what recording a version settled.
type SealedValue ¶
type SealedValue struct {
// Version is the write this is, which the ciphertext is bound to.
Version int
// Master names the key that wrapped the data key.
Master string
// Salt is what the wrapping key of this write was derived over, WrappedKey the data key
// wrapped, and WrapNonce what wrapped it.
Salt []byte
WrappedKey []byte
WrapNonce []byte
// Ciphertext is the value sealed under the data key, and Nonce what sealed it.
Ciphertext []byte
Nonce []byte
}
SealedValue is one value of the built-in store as the table keeps it: every part of what sealing it produced, and nothing that opens it.
type ServiceAccount ¶ added in v0.3.0
type ServiceAccount struct {
Namespace string
Name string
// CreatedBy is who created it, and empty on the namespace's built-in identity, NS/agentiik,
// which the installation creates with the namespace.
CreatedBy string
CreatedAt time.Time
}
ServiceAccount is a non-human principal of one namespace. Its principal is Namespace/Name.
func (ServiceAccount) Principal ¶ added in v0.3.0
func (s ServiceAccount) Principal() string
Principal is the string a grant names it by.
type Session ¶ added in v0.3.0
type Session struct {
Hash []byte
Login string
Credential string
// CredentialType is the type of the credential that opened it, as SessionByHash reads it:
// what a session a password opened may do is the policy's to say at each request.
CredentialType string
// BackupEligible is whether the passkey that opened it, where a passkey did, is synced, which
// device_bound_only refuses at each request as it refuses the passkey at a sign-in.
BackupEligible bool
// Admin is whether its user administers the installation, as SessionByHash reads it: an
// administrator's full session ends the bootstrap token at its first request while the token
// lasts.
Admin bool
CreatedAt time.Time
IdleExpiresAt time.Time
}
Session is a console session, without its identifier, opened by a credential of its user.
type SharedOutputs ¶ added in v0.4.0
type SharedOutputs struct {
SharedOutputs is a run of the workflow that republished outputs a run of another workflow of its namespace made, or one of another workflow that republished outputs of one of its runs: "a hit republishes the same envelopes without starting a container", naming the files the first run made, which a move would leave in one namespace while the run naming them is in the other.
func (*SharedOutputs) Error ¶ added in v0.4.0
func (e *SharedOutputs) Error() string
type SlotBucket ¶ added in v0.6.0
SlotBucket is what a runner, or a pool's runners together, held and offered in one bucket: the most tasks at once it held, and what it offered at the bucket's end.
type Status ¶
type Status string
Status is what has become of a reference.
A retired reference is kept rather than deleted, because a later request has to be able to tell this existed and is finished from this never existed, and because "the run detail keeps showing the artifact's name, size and digest with its collection recorded".
const ( // Live is a reference that can still be fetched. Live Status = "live" // Expired is a reference whose duration ran out. Expired Status = "expired" // Collected is a reference whose fetch budget was spent. The word is the // documentation's: "A one-shot artifact collected by its owner". Collected Status = "collected" )
type StepBucket ¶ added in v0.6.0
type StepBucket struct {
// Attempts are the attempts it was handed out, retries and shards included: a shard of a
// fan-out is an attempt of its own, and a lost dispatch handed out again is the same one.
Attempts int
// Duration is how long the attempts that ended ran, from their last dispatch to their end.
Duration Percentiles
// ExitCodes are the attempts that ended by the exit code they ended with, the most frequent
// first, one with none under a nil code.
ExitCodes []ExitCodeCount
// ItemsPerMinute is, for a step that fans out, the items its shards consumed a minute while
// any of them ran, and nil for any other step or where none ran.
ItemsPerMinute *float64
}
StepBucket is what one step came to in the runs created in one bucket.
type StepLog ¶
type StepLog struct {
Run agk.RunState
Verdict agk.Verdict
// Expired is a run whose retention has run out, whose logs the purge takes or has taken.
Expired bool
Dispatches []Dispatch
}
StepLog is where the log of one step stands: whether anything more can be dispatched for it, and every dispatch it has had, in the order they were made.
type StepRow ¶
type StepRow struct {
Step agk.Step
Verdict agk.Verdict
Attempts int
StartedAt time.Time
FinishedAt time.Time
}
StepRow is a step as the projection holds it.
type StepStrip ¶ added in v0.6.0
type StepStrip struct {
Step agk.Step `json:"step"`
Verdict agk.Verdict `json:"verdict"`
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
}
StepStrip is one step of a listed run, as its strip draws it.
type StepSummary ¶
type StepSummary struct {
Step agk.Step `json:"step"`
Verdict agk.Verdict `json:"verdict"`
Attempts int `json:"attempts"`
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
// Ports are the envelope digests the step published, which is what the database keeps of
// them. Never the items.
Ports map[agk.Port]Envelope `json:"ports,omitempty"`
// Image, InputPorts and OutputPorts are what the version the run pinned declares of the step:
// the image it runs, by digest, and the ports it reads and publishes. The API reads them from
// that version's graph, which the database holds as the document it was built from rather than
// as a second copy that could disagree with it.
Image string `json:"image,omitempty"`
InputPorts []agk.Port `json:"input_ports,omitempty"`
OutputPorts []agk.Port `json:"output_ports,omitempty"`
}
StepSummary is one step of a run, as a screen shows it.
type Stopped ¶
type Stopped struct {
// ExitCode is the code the container exited with, and nil where no container reported one.
ExitCode *int
StartedAt time.Time
Log agk.LogURI
LogLines int
LogCut bool
Usage map[string]any
}
Stopped is what a runner reports of a dispatch the controller stopped that the evaluator does not take: all of it for a task a run's ending stopped, and all but the exit code for one stopped while the run went on, since the task was over before the report came.
type TOTPEnrolment ¶ added in v0.3.0
type TOTPEnrolment struct {
Login string
ID string
Sealed []byte
StartedAt time.Time
ExpiresAt time.Time
}
TOTPEnrolment is a TOTP generator started and not confirmed: its secret, sealed as the row of credentials it becomes will hold it, under the identifier it will be enrolled with. It signs nobody in and asks no sign-in for a code until its first code confirms it.
type TaskLog ¶
type TaskLog struct {
Namespace string
// Row is the dispatch, and Task the key it is a dispatch of, which is what the log's URI
// names: a requeue after loss keeps its key and has a log of its own under its own row.
Row string
Task agk.TaskID
// NextSeq is the chunk the API expects next, and ShippedLines how far into the log the
// runner has shipped by its own count, which is where that chunk has to begin.
NextSeq int
ShippedLines int
// Lines, Bytes and Truncated are what the API holds.
Lines int
Bytes int64
Truncated bool
// FinalSeq is the chunk that closed the log, and zero while nothing has.
FinalSeq int
}
TaskLog is where one dispatch's log stands.
type TaskRow ¶
type TaskRow struct {
ID agk.TaskID
Step agk.Step
State agk.TaskState
Attempt int
Shard agk.Shard
Requeue int
Runner string
ExitCode *int
Log agk.LogURI
LogLines int
LogCut bool
// Usage is what the attempt cost, as the runner measured it. Nothing here reads it:
// it is carried so that a person, a console and a bill can.
Usage map[string]any
DispatchedAt time.Time
StartedAt time.Time
FinishedAt time.Time
Deadline time.Time
PublishedAt time.Time
// ReadyAt is when an attempt that waits out a retry's backoff may be handed out, and zero for
// any other task, which is ready when its row is first written. It is written once, with the
// row, and is what a task's queue wait is read from: see migration 0063.
ReadyAt time.Time
// MemoisedFrom is the run whose task published what a cache hit republished for this one,
// which no container ran.
MemoisedFrom agk.RunID
// CalledRun is the run a call started, where the task is a workflow: step's, which no
// runner holds.
CalledRun agk.RunID
}
TaskRow is one task as the projection holds it.
ID is the idempotency key, and it is never written: the database computes the same string for itself from the four columns that make it, and a caller writing the key would be a second place it could be got wrong. The ULID the row is keyed by is minted when the row is first written.
Requeue is which dispatch of the key the row records, as graph.ShardState counts them. It is what makes a requeue after loss a row of its own under the same key rather than the lost row written over.
type TaskSummary ¶
type TaskSummary struct {
Task agk.TaskID `json:"task"`
Step agk.Step `json:"step"`
State agk.TaskState `json:"state"`
Attempt int `json:"attempt"`
Shard *agk.Shard `json:"shard,omitempty"`
Runner string `json:"runner,omitempty"`
ExitCode *int `json:"exit_code,omitempty"`
StartedAt time.Time `json:"started_at,omitzero"`
FinishedAt time.Time `json:"finished_at,omitzero"`
// MemoisedFrom is the run whose task published what a cache hit republished for this one:
// "a hit republishes the same envelopes without starting a container", so no runner and no
// exit code are named, and this says where the outputs were made.
MemoisedFrom agk.RunID `json:"memoised_from,omitempty"`
// Called is the run a call started, where the task is a workflow: step's, which no runner
// held: its ending is that run's.
Called agk.RunID `json:"called,omitempty"`
// Inputs are the envelopes the task was handed on its input ports, by digest as a step's
// ports are, from the grant it was dispatched with. A task never dispatched has none.
Inputs map[agk.Port]Envelope `json:"inputs,omitempty"`
// Params are the parameters it was dispatched with, resolved, from the same grant. An
// expression may carry envelope contents into them, so the API answers them under
// run:read_data alone, as it does a run's inputs.
Params map[string]any `json:"params,omitempty"`
}
TaskSummary is one task, which is one shard of one attempt.
type Term ¶
type Term struct {
// Token is the acquisition counter, raised by whoever takes the lock. It only goes
// up, so a write carrying an older one is a write from a former holder.
Token int64
// Holder is the name that controller was given, and AcquiredAt when it took the lock.
// Neither decides anything: they are what a person reads during an incident.
Holder string
AcquiredAt time.Time
}
Term is one controller's period as the active one.
type TooManyChallenges ¶ added in v0.3.0
TooManyChallenges is a challenge refused because ChallengesLive challenges are open. FreeAt is when the oldest of them lapses, the first moment another fits.
func (*TooManyChallenges) Error ¶ added in v0.3.0
func (e *TooManyChallenges) Error() string
type TracedDispatch ¶
type TracedDispatch struct {
// ID is the dispatch's task_id, which names its span.
ID string
Key agk.TaskID
Step agk.Step
Attempt int
Shard agk.Shard
Requeue int
State agk.TaskState
Runner string
ExitCode *int
DispatchedAt time.Time
PublishedAt time.Time
StartedAt time.Time
FinishedAt time.Time
}
TracedDispatch is one row of the tasks table: one dispatch of one key.
type TreeFile ¶
type TreeFile struct {
Path string `json:"path"`
SHA256 string `json:"sha256"`
Size int64 `json:"size"`
// Mode is git's, 0644 or 0755 where the file is executable, and it is always written.
// Git tracks that one bit and a container needs it: an entry point that arrives 0644 is
// a step that will not run.
Mode string `json:"mode"`
}
TreeFile is one file of the repository, at the path the container sees it under /agk/repo.
The field names are the wire's: a redemption answers path, mode and sha256 for each file, and a stored shape that spelt the digest differently would be a translation somebody has to remember.
type TriggerContext ¶ added in v0.5.0
type TriggerContext struct {
Trigger map[string]any `json:"trigger,omitempty"`
Event map[string]any `json:"event,omitempty"`
}
TriggerContext is what fired a run as expressions read it: the trigger root, "body, headers, query, scheduled_for", and the event an event trigger matched. Frozen on the run, so that the controller starts the evaluator with it, a controller taking over reads the same, and "a replay sees what fired it, not what is true now".
type Unarmed ¶ added in v0.5.0
Unarmed is a workflow whose default branch's head is not what it has armed: its commit, and the head, empty while the branch is unborn.
type Unrecorded ¶ added in v0.3.0
type Unrecorded struct {
Namespace string
Run agk.RunID
// Envelopes are the digests of the envelopes the run keeps, the bare hexadecimal, whose files
// are its artifacts: what its steps published, and what their shards produced, as a decision
// records them, which includes the shards of a step that never published because another
// failed.
Envelopes []string
}
Unrecorded is one finished run whose artifact files are still to be recorded.
type Upload ¶ added in v0.3.0
type Upload struct {
// Digest is the object's, sixty-four lowercase hexadecimal characters, as a key writes it.
Digest string
// Length is the most the object may be, and negative where the request carrying it states
// no length, which is then given the room left.
Length int64
// Most is artifact_max_bytes, which bounds the room an object of no stated length is
// given, and zero bounds nothing.
Most int64
// Until is when the policy or the URL it is written with expires.
Until time.Time
}
Upload is one write room is made for.
type User ¶ added in v0.3.0
type User struct {
Login string
// Email is the address an administrator gave the user, for the people they work with to reach
// them by, and empty where none was given. Nothing sends anything to it.
Email string
// Admin is a platform administrator, which grants no run:read_data anywhere.
Admin bool
// Suspended is an account that opens no session.
Suspended bool
// SuspendedFor is why the authentication policy suspended it, SuspendedNoPasskey, and empty
// where it is not suspended or was suspended for no reason recorded.
SuspendedFor string
// Profile is what the user says of themself, theirs to write, save the given and family names
// an administrator may give at the creation.
Profile
// AvatarUpdatedAt is when the user's photo was last set, and zero where they have none. The
// photo itself is read on its own (Avatar), so that a listing of users carries none.
AvatarUpdatedAt time.Time
CreatedAt time.Time
LastSignInAt time.Time
}
User is a local account, and nothing it proves itself with.
func (User) DisplayName ¶ added in v0.3.0
DisplayName is the name people read for the user: their given name and their family name, each trimmed of the spaces at its ends and joined by one space, either alone where only one is said, and their login where neither is. Nobody writes it, so that it never says otherwise than the names the user writes.
type Variable ¶ added in v0.6.0
type Variable struct {
Name string
// Value is the value as JSON, as the API wrote it: every number as it was written but for an
// exponent, written out with a point. Read back, it is what jsonb writes, the same value.
Value json.RawMessage
// Bytes and Values are what the namespace's bounds are counted from: the bytes the value takes
// written as compact JSON, and how many values it holds, itself and everything in it.
Bytes, Values int
// Visibility is VisibilityAll or VisibilitySelected, and Workflows the workflows a selected
// one names, sorted and each once, empty for none; nil for all.
Visibility string
Workflows []string
UpdatedBy string
UpdatedAt time.Time
}
Variable is one variable of one namespace.
type VariablesFull ¶ added in v0.6.0
type VariablesFull struct{ Why string }
VariablesFull is a variable refused because the namespace's variables would be past what they may hold together. Nothing is written before it is answered.
func (*VariablesFull) Error ¶ added in v0.6.0
func (e *VariablesFull) Error() string
type Version ¶
type Version struct {
Namespace string
Workflow string
Commit string
Parent string
// Entry is the path of the entry point in the tree, Document is what it held, and
// Includes are the files it pulled in, by the path each was named at. Manifests are the
// brick manifests of every image the workflow names, by image reference. Images are the
// references the workflow names by tag, each with the digest it was resolved to when the
// version was pushed, written name@sha256:<hex>.
//
// Together these are what the graph is rebuilt from: loading them back gives the same
// workflow resolved the same way, with nothing fetched from anywhere, and every run of it
// names the same image bytes.
Entry string
Document []byte
Includes map[string][]byte
Manifests map[string][]byte
Images map[string]string
// Library says the commit is a library's: its root agentiik.yaml is written as a fragment,
// which another workflow includes and nothing runs. Document is that file and Includes what
// it includes of its own tree, and there are no manifests and no images, since it names no
// step a run starts.
Library bool
// Libraries are what each workflow include read, by the reference the file wrote it with,
// <namespace>/<name>@<ref>: the commit it resolved to at the push and the files of that
// commit resolution read. They are part of what the graph is rebuilt from, as Includes are,
// since another repository may since have moved its tag, been renamed or been deleted, and
// none of that may change what a run of this version does.
Libraries map[string]LibraryFiles
// Tree is the repository as the runner will see it, named rather than carried: "every
// step of every run sees it, mounted read-only at /agk/repo". The bytes are objects in
// the namespace's store, addressed by digest like everything else, so a file that did
// not change between two commits is one object and a version costs what changed.
//
// Deliberately not the same thing as Includes, and held in a column of its own rather
// than beside them. Those are what it takes to rebuild the graph with nothing in reach,
// which has to keep working when the object store is unreachable. This is what a
// container is given, and nothing rebuilds a graph from it.
Tree []TreeFile
Author string
CreatedAt time.Time
// Source is how the version arrived, SourceGit or SourceTree. Empty is SourceTree: the tree
// agk push sends through PUT /api/v1/{ns}/workflows/{name}/versions/{commit}, which was the one
// way a version arrived before a repository was hosted, and what its callers record.
Source string
}
Version is one commit of one workflow, as the database holds it.
type Wide ¶
type Wide struct {
// contains filtered or unexported fields
}
Wide is a handle on the installation, inside one transaction.
It sees every namespace, which is why it exists and why it is named rather than reached. Everything it is legitimately for is in Reason.
func (*Wide) AccessGrantsAcross ¶ added in v0.3.0
func (w *Wide) AccessGrantsAcross(ctx context.Context, p access.Principal, now time.Time) ([]access.Grant, error)
AccessGrantsAcross answers the grants that may apply at now to p, its own and its groups', in every namespace and at both scopes, for a listing that spans the namespaces its caller can read.
func (*Wide) Actionable ¶
Actionable names the runs a sweep should look at.
"A controller that was restarting therefore misses notifications, so it also sweeps for actionable work on a fixed interval. The notification is a latency optimisation; the sweep is the correctness guarantee." So this has to find everything a notification would have, which is four things: a run that has never been decided, a run whose clock has come round, a run holding a task whose message never went, and a run somebody has asked to cancel, whose clock says nothing about when that was.
A run decided with nothing on the clock is none of them. It waits on tasks in flight, and what it waits for sets its clock to the moment it arrived: a result, written with the decision that records it, and a loss, whether the heartbeat declared it or a runner reported it. Read as never decided, as it once was, such a run was decided again on every sweep, with nothing new to decide.
func (*Wide) ActivityStatistics ¶ added in v0.6.0
func (w *Wide) ActivityStatistics(ctx context.Context, b Buckets) ([]ActivityBucket, Activity, error)
ActivityStatistics counts what every namespace did, bucket by bucket, every bucket answered, oldest first, and reads what the installation is doing now. A namespace's runs and tasks count within its retention, as in every series, so that the installation's figures add up to its namespaces'.
func (*Wide) AddCredential ¶ added in v0.3.0
func (w *Wide) AddCredential(ctx context.Context, c Credential) error
AddCredential enrols one. A TOTP generator is enrolled beside a password alone, and is ErrNoPassword for a user holding none; one enrolled with a step, the step of the code that confirmed it, accepts no code of that step or of one before it.
Enrolling a TOTP locks its user's password, which a sign-in writes once it holds the user's row: its caller holds the user's row first (HoldUser), as every act on an account does, or the two wait on each other.
func (*Wide) AddMember ¶ added in v0.3.0
AddMember puts a user in a group, and answers whether they were not in it already. Membership touches no grant: the group's grants are what its members gain.
func (*Wide) Administrators ¶ added in v0.3.0
func (w *Wide) Administrators(ctx context.Context) ([]Administrator, error)
Administrators answers the installation's administrators, ordered by login, and locks each of their rows until the transaction ends, so that two removals of administrators at once take turns in one order and the second counts what the first left. The lock is HoldUser's, which a row referring to a user does not wait on.
func (*Wide) Attribution ¶ added in v0.3.0
func (w *Wide) Attribution(ctx context.Context, namespace, workflow, principal string) (Attribution, error)
Attribution reads principal as it stands now in namespace, for a question about workflow, or about the namespace alone where workflow is empty. principal is a login or NS/NAME, as a run's triggered_by writes it; operator, which names no principal, reads as one that does not exist, and so does anything else no principal is named.
func (*Wide) Audit ¶
Audit appends r to the audit log as an act on the installation, in this handle's transaction.
func (*Wide) AuditEntries ¶
AuditEntries answers at most limit entries of the audit log after entry seq, in order.
func (*Wide) AuditHead ¶
AuditHead is how many entries the audit log has been given and the hash of the last.
func (*Wide) AuditIn ¶ added in v0.3.0
AuditIn appends r to the audit log as an act done in namespace, in this handle's transaction: for an act the installation does in a namespace no handle on it could be opened for yet, as the grant that makes a new namespace's owner one, written in the transaction that creates the namespace; for a grant written through the installation's handle, which reads who can sign in across the namespaces in the same transaction; and for one the controller does there, whose one door is the installation's, as a run ended because its principal may no longer start it.
func (*Wide) AuditPage ¶ added in v0.6.0
func (w *Wide) AuditPage(ctx context.Context, q AuditQuery) (entries []audit.Entry, head, verified int64, err error)
AuditPage answers a page of the audit log, the newest entries first, and where the chain stands: head, the last entry appended, and verified, the last one a controller proved the chain to.
The entries are read backwards along seq, which every entry is numbered by and the table is keyed on, so that a page of the latest is read at once whatever the log's length. A narrowing that matches little reads further for its page; the log is read by a person looking for something, and how far back it goes is the length of what they asked about.
func (*Wide) Authenticate ¶
Authenticate answers which runner a credential belongs to, and refuses one revoked past its grace and one past its rotate_by.
"Revoking a credential never destroys work already done", so a revoked runner is still opened until its ResultsAcceptedUntil, as revoked: what that lets it do is each route's to say, and none of them lets it take anything new. From that instant it is refused here rather than left to a check somewhere else, since after the grace "every call is 401". So is a credential past its rotate_by, which is the whole of the rotation window: "A credential past its rotate_by is refused everywhere, and that host joins again", because "a machine that has been dark for a month should be reconsidered rather than readmitted". The moment is the caller's, as every moment this package judges is.
A runner that has rotated holds two credentials until it presents the new one: the one it was answered, and the one it rotated with, which is what it still holds if the answer never reached it. Either opens the runner, each until its own rotate_by, and the Runner answered carries the rotate_by of the one presented. The first time the new one is presented, the old one is forgotten, since the runner has then shown it holds the new one and the old one is worth something only to whoever else has a copy.
func (*Wide) Avatar ¶ added in v0.6.0
Avatar reads a user's photo, the PNG SetAvatar wrote, and when it was set. A login no user holds is ErrNoPrincipal, and a user holding no photo ErrNoAvatar.
func (*Wide) Beat ¶
Beat records that a runner is there and what it says of itself, and answers what it is to stop.
"A runner posts one heartbeat every 10 seconds to the API, listing the idempotency keys it currently holds. One request covers every in-flight task on that host." What it writes is the moment against every task it named, which is what Lost compares against, and what the runner reported of itself, which is what the inventory shows.
What it answers to stop is the backstop for agentiik.stops, which keeps nothing: a runner that was disconnected when a stop went out hears it here within one interval, rather than running the container to its deadline. So it is each key the runner named whose dispatch bound to it has been ended cancelled or timed_out, since those are the two endings the control plane writes while a container may still be running. A lost dispatch is never among them, although the host may still hold it: a host that was only cut off finishes its key, and the ending it records is what answers a requeue that comes back to it. Nor is a dispatch bound to another runner, which after a requeue is one more reason the key alone decides nothing.
func (*Wide) BindUnredeemed ¶
func (w *Wide) BindUnredeemed(ctx context.Context, namespace string, key agk.TaskID, row, runner string) (string, error)
BindUnredeemed binds one dispatch nobody has redeemed to the runner whose ending of it is being written, and answers who holds it once that is done.
Two endings come for a dispatch no runner is bound to. A grant that would not redeem ends a dispatch that never reached a container and that no redemption bound: a runner redeems before it pulls, so a refused pull is reported by the runner the redemption bound, but a refused redemption binds nobody. And a requeue that comes back to the host which already ended its key is never redeemed at all: the host answers it from its record, through the runner that redeemed an earlier dispatch of the key. The runner reporting either is bound to the dispatch here, as a redemption would have bound it, so that no other runner can report a second ending for it and no redemption can follow. A dispatch somebody already holds keeps its holder, and the answer says who that is; the row is locked by the update, so a redemption racing it binds first or finds it bound.
It belongs in the transaction that writes the ending, and never in one of its own. Lost takes a bound dispatch in flight for one a runner redeemed, so a binding committed without its ending would be swept lost, counted from the dispatch, as if a container had run and its host gone quiet.
func (*Wide) BootstrapHeld ¶ added in v0.3.0
BootstrapHeld reads it as Bootstrap does, and holds the row until the transaction ends, so that an act of the bootstrap token and the enrolment that ends the token take turns: the act commits while the token is live, or reads that it has ended. Taken after the act's own rows and before its entries in the audit log, which is the order EndBootstrap's caller takes them in.
func (*Wide) CalledBy ¶ added in v0.5.0
CalledBy is the run the dispatch task called, in whichever namespace it is.
func (*Wide) CancelCalled ¶ added in v0.5.0
func (w *Wide) CancelCalled(ctx context.Context, run agk.RunID, task agk.TaskID, at time.Time) error
CancelCalled asks every run the calls of run started, or the one the dispatch task started where task is not empty, to be cancelled, as a person cancelling it asks: "propagate cancellation and timeout down to child runs". Each is decided by the controller, which reads the request there, and is told to. A run that has ended, or was asked already, is left as it is.
func (*Wide) CancelTasks ¶
func (w *Wide) CancelTasks(ctx context.Context, namespace string, run agk.RunID, at time.Time) ([]agk.TaskID, error)
CancelTasks moves to cancelled every task of a run that is not over, and answers the keys of those a runner had redeemed.
"cancelled: Stopped because the run was cancelled by a principal, by a concurrency group or by a merge: first." It belongs in the transaction that writes the cancellation, because the evaluator ends a run and leaves its tasks where they were: it names the ones a runner holds, to be stopped, and the endings those runners send back reach a run with nothing left to learn. Left in flight, a task whose message was still on the queue would redeem its grant and start a container for a run that had ended, and every one of them would count against max_concurrent_tasks for good. A dispatch the heartbeat declared lost keeps its loss, which is the one record that its runner went quiet.
The keys it answers are to be stopped whatever the evaluator's document says of them. A pass that published a task and died before recording the dispatch leaves the task pending in the document, where the evaluator names nothing to stop, and a runner that took the message meanwhile has redeemed its grant and started the container. The row knows, because the redemption bound it.
func (*Wide) Consumption ¶ added in v0.3.0
func (w *Wide) Consumption(ctx context.Context) ([]Consumption, error)
Consumption reads every namespace, in name order, with what it holds against its quotas.
Each count is read namespace by namespace, through the index its quota is counted with where it is enforced, so a scrape reads what is in flight, the last hour's runs and the live artifacts, never the history.
func (*Wide) CreateGroup ¶ added in v0.3.0
CreateGroup writes a group with no member, and the principal it is.
func (*Wide) CreateNamespace ¶ added in v0.2.1
CreateNamespace creates a namespace with its built-in identity, NS/agentiik, and answers whether it did: false is one that already existed, which is left as it was, so that an installation script run twice creates it once. A name that is a user's login is ErrNameTaken, one another namespace held before it was renamed a *NameHeld naming it, which is ErrNameTaken as well, and an owner nobody created ErrNoPrincipal. Its storage name is the name it is created with.
n.Kind is shared where it is empty, and n.Owner is written on the row alone: the grant that lets an owner act on the namespace is its creator's to write, beside this, with GrantAccess. The quotas are written as SetQuotas writes them, so a zero MaxConcurrentTasks starts at the table's default, 20, and a zero MaxRetentionDays keeps what the namespace's runs produce for ever.
The built-in identity is created with the namespace because "scheduled, webhook and event runs are attributed to" it, and it "holds no grant until an owner gives it one", so creating it grants nothing. A namespace v0.2 made has none until one is given it.
func (*Wide) CreateRunnerPool ¶
func (w *Wide) CreateRunnerPool(ctx context.Context, p RunnerPool) error
CreateRunnerPool writes one. It is the first thing that happens, before any token and any machine.
The table holds a pool to the grammar the wire gives it, the name, each label and each namespace, and refuses anything else with PostgreSQL's own error. The API says why in words of its own before it gets here.
func (*Wide) CreateServiceAccount ¶ added in v0.3.0
func (w *Wide) CreateServiceAccount(ctx context.Context, s ServiceAccount) error
CreateServiceAccount writes a service account and the principal it is. One in a namespace nobody created is ErrNoNamespace. The built-in identity is written with no CreatedBy, and every other with one, which the table holds.
func (*Wide) CreateUser ¶ added in v0.3.0
CreateUser writes a user and the principal it is, in one statement: their login, their given and family names and email address where an administrator gave them, and whether they administer or are suspended. The rest of the profile starts empty, the user's own to write.
func (*Wide) Credential ¶ added in v0.3.0
Credential reads one by its identifier, which for a passkey is the credential ID an assertion names.
func (*Wide) CredentialUsed ¶ added in v0.3.0
CredentialUsed records when a password or a TOTP was last used.
func (*Wide) CredentialsOf ¶ added in v0.3.0
CredentialsOf answers a user's, in the order they were enrolled.
func (*Wide) CurrentName ¶ added in v0.6.0
CurrentName answers the name the namespace that answers to name has now: name itself, where no namespace holds it as a former name, and otherwise the name of the namespace that does. "The old name stays the namespace's, as a former name, and is resolved wherever an address names a namespace." A name nobody holds is answered as it is, and found absent by whatever asks of it.
func (*Wide) DeletedAmong ¶ added in v0.4.0
DeletedAmong answers which of the workflows named, each a namespace and a name, are deleted and not yet purged, as Deleted answers one.
func (*Wide) Delivered ¶
Delivered records that those events have been handed to whoever wanted them.
Stamped after the push went out and never before, for the same reason a task's message is stamped after the bus took it: a push that never went and is marked as gone is a failure nobody hears about.
func (*Wide) DismissNotification ¶ added in v0.3.0
DismissNotification removes one of recipient's notifications, which it lists no more, and is ErrNoNotification where recipient is told nothing of that identifier as of now.
func (*Wide) Drain ¶
Drain tells a runner to stop taking work and finish what it holds, and answers the runner as it now stands.
"Results are accepted as usual; the runner takes nothing new but stays up." Who ordered it, when and why are written on the row, which the inventory answers, the audit log recording the order beside it, and the reason is what the heartbeat hands the runner for its own log. A runner already draining is answered as it stands, since the first order is the one it is obeying and a second would change nothing it does. A revoked one is refused with ErrRunnerRevoked, because a drain is less than it was already told and answering it would read as though the revocation had been lifted, and one that is not there with ErrNoRunner.
func (*Wide) DueSchedules ¶ added in v0.5.0
DueSchedules are the schedules, across every namespace, whose occurrence is due to fire at now, soonest first, at most batch of them.
func (*Wide) EndBootstrap ¶ added in v0.3.0
EndBootstrap ends the bootstrap token at the first administrator's enrolment, or at their first password sign-in to a full session, or the first request of one, where their enrolment opened none, forgetting its hash, and answers whether this was the end of it: a second enrolment, sign-in or request ends nothing more. Every first administrator's link still open is revoked with it, and the session each opened, since a link made with the token is the token's reach and ends where it does. The recovery codes the token issued end with it too, and are not revoked here but read as ended (openCode), so that the end takes the row of no code another transaction may hold while it waits on the bootstrap state. A new user's link it issued stays open, as the link that user was created with, so that a user created before the end enrols after it.
func (*Wide) EndSession ¶ added in v0.3.0
EndSession revokes the session whose identifier hashes to hash, live or not, and answers whether it revoked one: a sign-out. One that opens nothing now is revoked all the same, since a session a suspension silences would open again when the suspension is lifted, and its holder asked for it to end. Found by its hash alone, which only whoever holds its cookie can give.
func (*Wide) EndSessionsOpenedBy ¶ added in v0.3.0
func (w *Wide) EndSessionsOpenedBy(ctx context.Context, login, credential string, kept []byte, at time.Time) (int, error)
EndSessionsOpenedBy revokes at at the live sessions of login that credential opened, but the one whose identifier hashes to kept where it is given, and answers how many it revoked: what a password set anew ends, since whoever knew the one before may be who holds them, and the person setting it keeps the session they set it from.
func (*Wide) EndTOTPEnrolment ¶ added in v0.3.0
EndTOTPEnrolment forgets the generator login started under id, once confirmed; one started since under another identifier is kept.
func (*Wide) EndTasks ¶
func (w *Wide) EndTasks(ctx context.Context, namespace string, run agk.RunID, at time.Time) ([]agk.TaskID, error)
EndTasks ends every task of a run that has ended and is not over itself, with the ending the run's own ending names, and answers the keys of those a runner had redeemed. It is called in the transaction that writes the run's ending, after it, and refuses a run that has not ended.
A run that reached its deadline writes its tasks timed_out: "once it passes, the tasks still running are stopped and the run ends there." Every other ending writes them cancelled, and not only a cancellation's. A run that succeeded or failed has ended every step, and a step ends once every shard of it has, except the one a merge: first superseded: that step is cancelled the moment the barrier lifts on another edge, while its tasks may still be in flight and are only asked to stop. The evaluator ends every one of them cancelled as the barrier lifts, handed out or not, in whichever pass first reads the cancelled step, and the controller writes that, so such a run holds no task in flight in its document. A row the document does not describe is ended here all the same: its runner's ending would reach a run with nothing left to learn, and the row would read dispatched or running for ever. "cancelled: Stopped because the run was cancelled by a principal, by a concurrency group, by a merge: first or by fail_fast" is the ending for it.
It is CancelTasks for every way a run ends under its tasks, and for the same reasons: a message still on the queue would otherwise redeem its grant for a run that has ended, the run's tasks would count against max_concurrent_tasks for good, and the row is what names a runner's dispatch the document does not. It is also what the heartbeat answers cancel from, so that a runner that missed the stop on agentiik.stops hears it at its next heartbeat rather than running the container to its own deadline.
func (*Wide) EnrolmentCodeByHash ¶ added in v0.3.0
func (w *Wide) EnrolmentCodeByHash(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, error)
EnrolmentCodeByHash answers the code whose value hashes to hash, if it is open at now, as openCode says.
func (*Wide) Fence ¶
Fence refuses this transaction if the term has moved on.
Called at the top of every controller write, before anything is read or written, so that a former holder that has not noticed cannot act on state it no longer owns. The row is locked for the life of the transaction, so a controller taking the term waits for an in-flight write to finish rather than overlapping it, and everything that starts afterwards is refused.
func (*Wide) FirstCapacity ¶ added in v0.6.0
FirstCapacity is when a runner first reported what it offers before before, which is where the chart of the pools has something to draw, and the zero time where none has.
func (*Wide) FirstRun ¶ added in v0.6.0
FirstRun is when the first run of the workflows among, which the authorizer allowed, was created before before, as a series counts it, and the zero time where there is none: where a series asked with range=max starts.
func (*Wide) FirstRunAnywhere ¶ added in v0.6.0
FirstRunAnywhere is when the first run of any namespace was created before before, as the installation's activity counts it, and the zero time where there is none.
func (*Wide) Forget ¶ added in v0.4.0
Forget removes the entry a key names, which is how an entry found to name something no longer there is kept from being asked about again.
func (*Wide) GiveBuiltInIdentities ¶ added in v0.3.0
GiveBuiltInIdentities creates the built-in identity, NS/agentiik, of every namespace that has none, and answers the namespaces it gave one, ordered by name. Nothing is granted to any: it "holds no grant until an owner gives it one".
A namespace is created with its built-in identity from v0.3.0, so the ones that lack it are those v0.2 made, which an upgrade keeps: init and migrate give it them at every run, and a run that finds none lacking gives none. Two runs at once give each namespace one, the second finding the first's rows and leaving them. A namespace whose name no principal can be written with, one past the 255 characters v0.2 did not bound, is left without one rather than failing the upgrade, and is not in the answer.
func (*Wide) GrantAccess ¶ added in v0.3.0
GrantAccess writes a grant in whichever namespace its scope names, as NS.GrantAccess does in its own: for the installation's acts on a namespace, the grant that makes a new namespace's owner one among them, which is written in the transaction that creates the namespace, before any handle on it could be opened; and a grant carrying a role, written in the transaction that asks whether an administrator can still sign in once it applies, which reads their grants in every namespace.
func (*Wide) Groups ¶ added in v0.3.0
Groups is the listing, ordered by name, each with its members ordered by login.
func (*Wide) GroupsOf ¶ added in v0.3.0
GroupsOf answers the names of the groups a user is in, ordered, which with the login are the access.Principal a question about the user is asked with.
func (*Wide) HeldBy ¶
func (w *Wide) HeldBy(ctx context.Context, namespace string, key agk.TaskID, row string) (string, error)
HeldBy answers which runner one dispatch of a task was bound to when its grant was redeemed, and the empty string where nobody has redeemed it.
It is the binding Redeem made, read on the way out: a result is taken from the runner its task was bound to and from no other. The dispatch is named twice, by its row and by its key, and both are compared with what is recorded, for the reason Redeem compares them on the way in: a row of one task and the key of another is an answer somebody assembled out of two, and neither half is evidence about the other. The row is compared as text, because a runner wrote it and the column's domain would refuse a value that is not a ULID with an error rather than find nothing.
func (*Wide) HoldBootstrapToEnd ¶ added in v0.3.0
HoldBootstrapToEnd reads it as Bootstrap does, and holds the row to be written until the transaction ends: what the first administrator's enrolment takes after the user's row and before the code it spends, which is the order issuing a first administrator's link takes them in, so that a link issued at the same moment revokes the code before it is spent or waits for the enrolment to end the bootstrap, and neither waits on the other.
func (*Wide) HoldMember ¶ added in v0.3.0
HoldMember holds for key share what removing login takes before their user row, in the order it takes them: their personal namespace, where there is one, and then their principal. A membership telling the owners of the namespaces its group holds a role in, among whom the member may now be, holds the member's principal as each recipient's, and their personal namespace where the group holds a role there, after the insert took the member's user row; the removal takes the namespace, the principal and then the user row. Held first, a membership and a removal of its member take turns, where otherwise each would hold what the other waits for. A login whose principal is gone is ErrNoPrincipal.
func (*Wide) HoldUser ¶ added in v0.3.0
HoldUser reads one by login as User does, and holds its row until the transaction ends: an enrolment takes the user's row first, as issuing a link does, so that the two take turns rather than each waiting on what the other took.
The row is held against every other act that holds or writes it, and not against a row written elsewhere that refers to it, a membership, a credential or a challenge, which takes the weaker lock a reference takes: an act holding many users' rows, as forbidding passwords holds every one, would otherwise wait on a group created with two of them as members in the other order, while the group waits on it.
func (*Wide) Holding ¶
Holding names the run that holds a concurrency group, and whether it is this one.
A run holds its group once it has started. A queued run holds nothing, which is what lets several queue up behind one without any of them believing it is in charge. The oldest queued run is the one that goes next, because a group that let the newest through would starve the first arrival for as long as triggers kept firing.
func (*Wide) ImportBootstrapToken ¶ added in v0.3.0
ImportBootstrapToken keeps hash as the bootstrap token's where no hash is kept and the token has not ended, and answers whether it did. It is how migrate brings in, once, the hash a v0.2 installation kept in a file: a hash kept already is the one the installation's settings gave since, which an old file never replaces, and an ended token stays ended.
One statement, so that a hash another run writes between the caller's read and this write is kept rather than overwritten.
func (*Wide) InstallationPolicy ¶ added in v0.3.0
func (w *Wide) InstallationPolicy(ctx context.Context) (AuthPolicy, error)
InstallationPolicy reads the installation's, which the migration wrote at the documented defaults and an administrator may have changed since.
func (*Wide) IssueChallenge ¶ added in v0.3.0
IssueChallenge keeps a challenge until it is taken or its minutes pass, and removes some of those whose minutes passed before c was issued, so that the table holds what the last few minutes of ceremonies started and little older. Where ChallengesLive are open as c is issued, it writes nothing and is *TooManyChallenges.
The open challenges are counted in the order they lapse, and no further than the bound, so that a refusal reads ChallengesLive entries of the index and no more, and learns from the first when one lapses. Two ceremonies started at once may both count one under the bound and both be kept, so the table may hold a few more than it, as many as there are transactions starting a ceremony at the same moment, which the API's connections bound: the bound is there to keep a flood from filling the table, which a handful over it does not.
The removal skips a row another transaction holds rather than waiting for it: two ceremonies started at once each find the same lapsed rows, and one waiting on the other's removal, or the two taking them in two orders, would make ceremonies anybody may start wait on each other.
func (*Wide) IssueEnrolmentCode ¶ added in v0.3.0
IssueEnrolmentCode writes a code, revoking at its IssuedAt the code it replaces, and answers whether there was one: a link issued again leaves the one before it unusable. A new user's link or a recovery code replaces the user's open code of its kind. A first administrator's link replaces every open one, whoever it was for, and is ErrBootstrapEnded once the first administrator has enrolled.
A first administrator's link and a new user's link are for a user who holds no credential yet, and are ErrEnrolled for one who does; a recovery code is for one who lost theirs.
The user's row is locked first, and the bootstrap state's for a first administrator's link, so that two issues at once take turns and the second replaces the first rather than failing on it. Whether the user holds a credential is read once the row is locked, so that an enrolment still committing is waited for and seen, rather than answered with a link beside the passkey it made.
func (*Wide) IssueExchangeCode ¶ added in v0.3.0
func (w *Wide) IssueExchangeCode(ctx context.Context, c ExchangeCode) error
IssueExchangeCode keeps a code until it is taken or its minute passes, and removes some of those whose minute passed before c was issued, skipping a row another transaction holds, as IssueChallenge does. A login no user holds is ErrNoPrincipal, and a credential that is not theirs, removed since the sign-in included, ErrNoCredential.
func (*Wide) IssueGrant ¶
func (w *Wide) IssueGrant(ctx context.Context, namespace string, task agk.TaskID, id string, scope GrantScope, until time.Time) (Granted, error)
IssueGrant mints the grant for one task and records what it takes to check it.
The row is written by the controller inside the decision that planned the task, so a task that exists has a grant and a grant belongs to a task that exists. The clear value is answered here and nowhere else: it goes into the message and is then unrecoverable.
Each call adds a grant beside those the row already has, and replaces none of them. A task is issued one again when a pass published it and could not record the dispatch, so the next pass plans it and publishes it again, and the message that went first may be the only one on the queue: the stream deduplicates a task on its row. Replaced, the grant that message carries would open nothing, and the runner taking it would be left to report a task that never reached a container, which ends it. Kept, whichever message a runner takes redeems, and the first redemption binds the task for all of them.
func (*Wide) IssueJoinToken ¶
func (w *Wide) IssueJoinToken(ctx context.Context, pool string, labels []string, by string, at, until time.Time) (JoinToken, error)
IssueJoinToken mints one, bound to one pool and one set of labels, issued at one moment and good until another.
"bound both to that pool and to the exact set of labels a runner may claim with it", because "a machine cannot add zone=lan to itself and start receiving the steps that were kept off the internet".
Both moments are the caller's, as a join's is, because the wire writes issued_at "on the clock of the API that created it" and the expiry is read against it: a token stamped by one clock and timed by another would say it lived a different hour from the one it was given.
func (*Wide) Join ¶
func (w *Wide) Join(ctx context.Context, j Joining, rotateAfter time.Duration, now time.Time) (Joined, error)
Join redeems a token and creates the runner.
Everything about it is checked against the token rather than believed: the pool is the token's, and the labels have to be a subset of what the token permits. A machine that claimed more is refused rather than trimmed, because trimming would let it join with less than it asked for and then wonder why it is being offered nothing.
func (*Wide) LiftSuspension ¶ added in v0.3.0
LiftSuspension lifts login's suspension where it was made for reason, and answers whether it did: a suspension made for another reason, or for none recorded, is not the caller's to lift. Its caller holds the user's row (HoldUser).
func (*Wide) ListWorkflows ¶ added in v0.6.0
ListWorkflows answers the workflows given, those not deleted, each with its newest run, by name in byte order: the second half of a namespace's listing, given the workflows the authorizer allowed. None given reads nothing, as Runs reads nothing, since the filter is the authorisation decision and a missing one fails closed.
func (*Wide) Listening ¶ added in v0.5.0
func (w *Wide) Listening(ctx context.Context, published, eventType, source string) ([]Listening, error)
Listening are the event triggers, across every namespace, that hear the namespace published into and whose type and source, each where it names one, are the event's: in the namespace published into first, then by namespace, workflow and position. Whether one armed in another namespace may hear it is the authorizer's to say, and its filter the graph's.
A trigger hears a namespace by any name it answers to, its own or one it held before a rename, since a workflow of another namespace keeps the name it was written with until somebody changes it, and "a workflow naming the old name keeps working". The rename writes the triggers armed then under the new name; one armed since from a file naming the old one names it still.
func (*Wide) LiveTokens ¶ added in v0.3.0
LiveTokens answers how many of a principal's tokens are neither revoked nor expired at now, a suspended user's included, since they open again when the suspension is lifted. It locks the principal's row until the transaction ends, so that two tokens minted for one principal at once are counted one after the other and a bound on the count holds; a principal nobody created is ErrNoPrincipal.
func (*Wide) Locate ¶
Locate says which namespace and workflow a run is of, from its identifier alone.
It is what a route about one run is authorised against: the path of such a route names the run and nothing it is of, and a permission such as workflow:run can be held on a single workflow. The identifier comes from a path, so one outside the alphabet runs are minted in is no run, answered without asking PostgreSQL: the column's domain refuses it with an error rather than finding nothing, and so does the protocol for U+0000 or bytes that are not UTF-8, which would have been a 500 for anybody holding a credential.
func (*Wide) LogObjectRecorded ¶
LogObjectRecorded says whether RecordLogObject recorded that key for that log, and not only asked to: a key is written to only once it could be purged.
func (*Wide) Logins ¶ added in v0.3.0
Logins answers the login of every user, ordered by login: those an installation's policy applies to.
func (*Wide) Lose ¶
func (w *Wide) Lose(ctx context.Context, namespace string, key agk.TaskID, row, runner string, at time.Time) (bool, error)
Lose moves to lost the one dispatch a loss names, where it is bound to the runner the loss names and still in flight, and answers whether anything moved.
"lost is declared by the controller rather than reported here, and travels on a result only where a runner recovers one it had already lost." Such a result is written where the heartbeat writes its own losses, so that the evaluator hears of both the same way.
The dispatch is named by its task_id rather than found by its key. A requeue keeps the key, and one runner may hold two dispatches of a key over time: the one it lost, and the requeue it took afterwards. Found by the key and the runner, a loss it reported about the first, late or delivered again, would land on the second and requeue a task that is running perfectly well. Named, it finds the first already lost and moves nothing, which is also what makes a loss delivered twice requeue once.
It reaches only a dispatch bound to that runner, for the reason a heartbeat keeps alive only a runner's own tasks: a runner able to declare somebody else's task lost could send work round the fleet that is running perfectly well. A dispatch of the key bound to another runner, or to none, or no dispatch of the key at all, is answered ErrNotHeld. And it moves only one still in flight, which is one that runner redeemed: a runner bound by reporting that a task never reached a container was bound with that ending, so the dispatch is over and nothing moves.
That runner is the one the result names, and it is the one that published it: a heartbeat is a request the API authenticates, and a result arrives on a subject only its runner's credential may publish on, which package bus/control holds the result's runner field to. So this keeps off another's task both a runner that is wrong about what it holds and one that lies about its name.
func (*Wide) Losses ¶
Losses names the dispatches of one run that are lost and that nothing has requeued.
It is how the controller hears what its sweep declared. "Liveness therefore lives in the database beside the task state", so a loss is written here first, by Lost or by Lose, and the evaluator is told on the next pass rather than by whoever noticed: a requeue is a decision, and deciding is the controller's. A dispatch already requeued past is not named, since the loss has been heard; one that was not requeued, because its step is not idempotent, its policy does not name lost or its key was already handed out again as often as max_requeues allows, is named on every pass and changes nothing on any but the first.
func (*Wide) Lost ¶
Lost moves the tasks of runners that stopped reporting, as of now, and answers how many it moved.
"Three missed intervals move a task to lost, which is the state whose consequences Lifecycle and replay describes." A task is lost rather than failed, and the distinction is the whole of why this exists: "A failed task is charged to the brick and follows the retry policy; a lost task is charged to the infrastructure and is requeued only when the step is declared idempotent, since it may well have completed without the result coming back."
It is the controller's sweep and judges by the controller's clock, though not everything it judges was stamped by that clock: the dispatch was, and the heartbeat and the redemption were stamped by the API's. So it rests on the two agreeing, as a grant already does, whose expiry the controller sets and the API judges. A heartbeat is at most one interval old when the next one lands, so a controller less than two intervals ahead of the API still finds a runner reporting on time, and one behind it declares a loss that much later. Judging by the database's clock would not have removed the pairing, only added a third clock to it.
Only a task some runner holds, which is one a runner has redeemed the grant of. A task nobody has redeemed is a message waiting on the queue for a runner with room, or one a runner took and has not redeemed yet, and so has not acknowledged either, since a runner acknowledges only once it has redeemed: should it die there, the bus hands the message to another runner of the pool once AckWait has passed. Or it is a requeue that came back to the host which had already ended its key, which nobody redeems: that host publishes the ending it recorded before it acknowledges the message, so the ending is on the result stream by the time the message leaves the queue, and binds the host's runner as it is written. Either way the task is the bus's until it is redeemed or answered, and a busy pool or an empty one keeps it waiting as long as it likes; it is not lost, because "lost: The runner holding it stopped reporting" and nothing holds it. Declared lost, it would be requeued into the queue it was already waiting on, one row and one message on every sweep for as long as the pool stayed full, and a step that does not requeue would fail for having waited.
Held is read as bound to a runner, and a task in flight is bound by a redemption and by nothing else. A runner is also bound to a task it reports never reached a container, and that binding is written with the ending, in one transaction, so the task is over by the time it is bound and never in flight with a runner that did not redeem it.
A task that is held counts from the last thing its runner said about it: its last heartbeat, or its redemption where no heartbeat has named it yet, and the dispatch only where neither is recorded. Not from the dispatch alone, which is when the message went on the queue: a task redeemed after a long wait would be lost between its redemption and its first heartbeat, and requeued while its container ran. A runner that redeemed a task and was never heard from again, one that died before it could acknowledge the message included, is still exactly the case this is for, counted from its redemption. The redemption is the latest of its grants', since a task may have been issued several and a runner redeems one: joined on each, the one nobody redeemed would count the task from its dispatch.
The runs are locked before their tasks, which is the order a decision takes them in: SaveDecision updates the run and then writes each of its tasks. Taken the other way round, a sweep holding a task and waiting on its run, while a decision held the run and reached the task, would be a deadlock, and PostgreSQL would end one of the two. Neither is waited on where somebody else holds it: a run being decided is passed over with its tasks, a task that a redemption, a heartbeat or a runner's own loss holds is passed over alone, and each is judged again on the next sweep. A sweep that waited would wait on whatever that was, and every run behind it with it.
The tasks are locked by one statement and judged by the next. PostgreSQL rechecks a row that changed before it could be locked against the row as it now stands and every other table as it stood, so a redemption that committed in between would be judged with its binding and without its grant, and counted from the dispatch. Judged once they are locked, a task redeemed before the lock counts from its redemption, and a redemption after it waits and finds the task lost.
What it writes is the dispatch's row and the run's wake, and nothing about a requeue. Whether the task is handed out again is the evaluator's to say, and the controller hears of the loss through Losses on the pass the wake brings round.
func (*Wide) MemoAlive ¶ added in v0.4.0
func (w *Wide) MemoAlive(ctx context.Context, namespace string, m Memo, files []agk.URI) (bool, error)
MemoAlive says whether everything a cache entry would hand back is still there, and a hit therefore one: "a cache entry pointing at an expired artifact is not a hit". Its run's envelopes not purged; each envelope's object counted and not being collected; and each file its items name a live artifact with no fetch budget, since a one-shot artifact republished would be fetched by two runs out of a budget set for one.
Asked in the transaction that records the hit, so that the answer holds for what is written with it: a collection that claims an object after this has to find it counted again.
func (*Wide) Memoise ¶ added in v0.4.0
Memoise records what a cached task published under its key, replacing an entry the key held: the latest run's envelopes are the ones kept the longest.
func (*Wide) MintToken ¶ added in v0.3.0
MintToken writes a token for a principal, which is a user or a service account. CreatedAt and ExpiresAt are the caller's, read off one clock, since the table refuses an expiry more than a year after creation.
func (*Wide) NameHolder ¶ added in v0.6.0
NameHolder answers who holds name, as a namespace a rename would give it is refused it: a user's login, a namespace's name, a namespace's former name, or nil for nobody.
func (*Wide) NamespaceAvatar ¶ added in v0.6.0
NamespaceAvatar reads a namespace's picture and when it was set. A namespace that does not exist is ErrNoNamespace, and one with no picture ErrNoNamespaceAvatar.
func (*Wide) NamespaceNamed ¶ added in v0.3.0
NamespaceNamed reads one.
func (*Wide) NamespacePolicy ¶ added in v0.3.0
NamespacePolicy reads what a namespace tightens, which is nothing where it has set nothing.
func (*Wide) Namespaces ¶ added in v0.3.0
Namespaces is the listing, ordered by name.
func (*Wide) NamespacesOwnedBy ¶ added in v0.3.0
NamespacesOwnedBy answers the namespaces whose record names principal as owner, ordered by name, which is what refuses its removal.
func (*Wide) NextInLine ¶
func (w *Wide) NextInLine(ctx context.Context, namespace, group string, run agk.RunID) (bool, error)
NextInLine says whether this run is the one a free group should let through.
Creation order, which is the only order that does not starve somebody: a group admitting the newest arrival would leave the first one queued for as long as triggers kept firing.
func (*Wide) NotificationsOf ¶ added in v0.3.0
func (w *Wide) NotificationsOf(ctx context.Context, recipient string, now time.Time) ([]Notification, error)
NotificationsOf answers what recipient is told as of now, newest first, and removes what it was told more than NotificationKept before now, which is kept no longer. Removed where it is read rather than by a sweep of its own: a notification nobody reads costs a row until its reader asks, or is removed with them, and one past its days is never answered either way.
func (*Wide) Occupancy ¶
Occupancy reads every runner heard from within LostAfter of now, in pool and runner order.
Only those, because a runner silent for longer holds nothing any more as far as the controller is concerned, its tasks being declared lost, and one that left for good would otherwise be reported for ever. So the gauges built from this hold the runners that exist at the moment of the scrape, however many have come and gone, which is what bounds them.
The tasks are counted once for every runner, from the in-flight rows alone, which the partial index tasks_held covers: a scrape reads what is running, never the history.
func (*Wide) OpenSession ¶ added in v0.3.0
OpenSession writes one. CreatedAt is the caller's, as IdleExpiresAt is. A suspended user opens none: an enrolment link or a recovery code still works for them, "since enrolling is how an account suspended for having no passkey comes back", through the registration it starts rather than through a session.
func (*Wide) Ownerless ¶ added in v0.3.0
Ownerless is the names of the namespaces whose record names no owner, ordered by name, each held for key share, as a grant written in one holds it: a removal under way is waited for, and the namespace it removes is left out rather than named to a grant that could no longer be written, and a removal that comes after waits for the transaction that read them.
func (*Wide) PasskeyHandle ¶ added in v0.3.0
PasskeyHandle answers the handle login's passkeys are registered under, keeping fresh as that handle where the user has none yet, and the one kept where they have: it is minted once, on the first registration started for them, and never changes, since every passkey registered under it hands it back. A login no user has is ErrNoPrincipal.
func (*Wide) PasskeyHandleOf ¶ added in v0.3.0
PasskeyHandleOf answers the handle login's passkeys are registered under, and nil where no registration was ever started for them. A login no user has is ErrNoPrincipal.
func (*Wide) PasskeyUsed ¶ added in v0.3.0
func (w *Wide) PasskeyUsed(ctx context.Context, id string, count uint32, backedUp bool, at time.Time) error
PasskeyUsed records an assertion made with a passkey: the counter and the Backup State it reported, and when. A counter that did not move past the recorded one is ErrSignCountBehind and nothing is recorded, checked in the statement that writes it, so that of two assertions verified against one reading the second is still refused.
func (*Wide) PoolStatistics ¶ added in v0.6.0
PoolStatistics answers every pool, by name, with its runners, by name, bucket by bucket: those that were in it at any time over the range, whether or not they are there now. A task holds a slot of its runner from when the runner redeemed it, or started it where no redemption is recorded, to when it ended, or until now for one that has not. A runner offers what it last wrote at the bucket's end, or nothing once it has been silent for lostAfter.
func (*Wide) PortStatistics ¶ added in v0.6.0
func (w *Wide) PortStatistics(ctx context.Context, of Workflow, b Buckets) (map[string][]map[string]int64, error)
PortStatistics counts what each step of the one workflow of published, port by port, bucket by bucket: the items of the envelope each port published, which the step's row records with its digest, from the envelope's meta.count and never its items. A port that published in no run of a bucket is absent from it; every bucket of a step that published anywhere is answered.
func (*Wide) Present ¶ added in v0.3.0
Present answers what NS.Present does of namespace, for an act on it the installation's handle writes, as a grant written with GrantAccess is.
func (*Wide) PrincipalKind ¶ added in v0.3.0
PrincipalKind answers what kind of principal a reference names, or ErrNoPrincipal. operator, which v0.2 wrote on the rows it left, names none.
func (*Wide) Progress ¶
func (w *Wide) Progress(ctx context.Context, namespace string, key agk.TaskID, row, runner string, to agk.TaskState) (bool, error)
Progress moves the one dispatch a progress message names to running or publishing, where it is bound to the runner the message names, and answers whether anything moved.
"running: The container is running. publishing: The container is finished; its outputs are being collected and uploaded." Only the runner holding a dispatch can see either, so it says so on its results subject, and this is where it is written: on the row alone, for a person reading the run. The evaluator's state is not told, since nothing it decides depends on either, and the row is what the run detail reads.
Only forwards, and never over an ending. Running moves a dispatched row, publishing a dispatched or running one, and a row already there or past it is left as it is, so a message delivered twice, out of order or after the result changes nothing, whichever commits first: the row is locked by the update, and one that waited on a decision writing the ending finds the ending. Nor on the row of a run that has ended, which has nothing to learn, as a result for one has not.
It reaches only a dispatch bound to that runner, for the reason Lose gives: a runner able to move somebody else's task could show work running that nobody runs. A dispatch bound to another runner, or to none, or no dispatch of the key at all, is answered ErrNotHeld. The dispatch is named by its task_id and its key together, for the reason HeldBy gives, so a host still running a dispatch that was declared lost moves nothing on the requeue somebody else may hold.
A dispatch bound to that runner and still pending is answered ErrNotYetDispatched, and moves nothing. The controller publishes a task before it records the dispatch, so a runner quick enough redeems, starts and reports a task the rows still hold as planned, and even more so where a pass publishing a few hundred shards records them all at the end, or dies before it does and leaves them to the next sweep. Written over pending, running would stand on a row Unpublished and Actionable no longer find, and a message whose pass died would never be sent again; taken as no news, it would be acknowledged and never said again, and the task would read dispatched until its ending. So it is left for a later delivery, by when the dispatch is recorded.
func (*Wide) Published ¶
func (w *Wide) Published(ctx context.Context, namespace string, keys []agk.TaskID, at time.Time) (int, error)
Published stamps the tasks whose messages have gone.
Called after the bus accepted them and never before, which is what makes the stamp mean what it says. A task with no stamp is one the sweep publishes again, and publishing one dispatch twice is free: the stream deduplicates it on its task_id, and a runner refuses a key it holds or has completed. The stream does not deduplicate on the key, because a requeue after loss keeps the key and takes a new task_id, and it is meant to go out.
func (*Wide) RecordLogObject ¶
RecordLogObject records that an object of a log is about to be written, in a transaction that commits before the write, so that the purge can name it whatever becomes of the transaction that records the chunk it holds. The task's row is given the log's URI with it, which is what the purge finds a log by.
func (*Wide) Redeem ¶
func (w *Wide) Redeem(ctx context.Context, clear string, task agk.TaskID, runner string, now time.Time) (Redeemed, error)
Redeem checks a grant, binds the task to the runner redeeming it, and answers what it is for.
The value names the task inside its own text and the caller names one too, and both are checked against the row: "the API refuses a redemption where the two disagree rather than believing either alone". A grant past its expiry is refused like one that never existed, because a credential that says how it failed is a credential that helps somebody find the next one.
Binding the task here is what makes at-least-once delivery safe on the way in. A message may be delivered twice and to two machines; the second one to redeem is told the work is somebody else's rather than starting a container for it. A runner redeems before it acknowledges the message, so this, and not the bus, is what decides whose a task is: the bus decides only who is handed it. The binding is never released, because a task whose runner was lost is moved to lost and requeued as a new row under the same key, with a grant of its own.
A key may therefore have several rows, one per dispatch, and the rule is about the key: "the runner refuses to start a container for a key that has already completed". The row is what is read, and it answers for the key because of the uniqueness rule on tasks: at most one row of a key is anything but lost, so a key that completed on one dispatch has every row over, and a key with a row still going has completed on none. A lost row is refused like any row that is over, since its dispatch was superseded by the requeue and the grant it carried opens nothing.
func (*Wide) Redeemable ¶
func (w *Wide) Redeemable(ctx context.Context, clear string, task agk.TaskID, runner string, now time.Time) (Redeemed, error)
Redeemable is Redeem without the binding: every check Redeem makes, refused the same way, and nothing written.
It is the first half of a redemption and Redeem the second. What the grant is for is read between the two, the secret values last, so that a value is read only for a grant that would redeem and a task is bound only once there is an answer to give the runner. One transaction for both would hold the task's row, and a connection, across a round trip to whichever store keeps the value. Redeem checks again under the lock, so a task bound, ended or expired in between is refused there and nothing is answered.
func (*Wide) RedeemedBefore ¶
func (w *Wide) RedeemedBefore(ctx context.Context, namespace string, key agk.TaskID, row, runner string) (bool, error)
RedeemedBefore answers whether a runner redeemed a dispatch of a key earlier than the one a row records.
It is what a requeue is answered from when it comes back to the host that already ended its key. That host refuses to run the key again and reports the ending it recorded under the requeue's task_id, and nobody redeems the requeue, so its ending cannot be held to a redemption of its own. It is held to the redemption of the dispatch the host ended, which is a dispatch of the same key handed out before it: the runner reporting it was given that work, so it reaches no further than "the tasks in its hands". A binding made by an ending that never reached a container is no redemption, and does not count; nor does a later dispatch, which cannot be what the requeue came back to.
func (*Wide) RemoveAvatar ¶ added in v0.6.0
RemoveAvatar removes a user's photo, and answers whether they held one. A login no user holds is ErrNoPrincipal, told apart from a user holding no photo, which removing changes nothing of.
func (*Wide) RemoveCredential ¶ added in v0.3.0
RemoveCredential deletes one of a user's credentials, and with it every session it opened. Deleting a password is this: the row goes, and nothing is left to blank, and the user's TOTP generator goes with it, since a TOTP exists only alongside a password.
func (*Wide) RemoveMember ¶ added in v0.3.0
RemoveMember takes a user out of a group, and answers whether they were in it.
func (*Wide) RemoveNamespace ¶ added in v0.2.1
RemoveNamespace removes a namespace that holds no workflow, run, secret, stored object or service account but its built-in identity, and refuses one that does with a *NamespaceHolds. One that does not exist is ErrNoNamespace.
It removes a personal namespace as it removes a shared one: whether one may be removed, and by whom, is its caller's to say, since the route that removes a namespace refuses a personal one and removing a user takes their empty personal namespace with them.
The built-in identity goes first, with the tokens and grants it holds: it is the namespace's own and nobody created it, so it is no reason to keep the namespace, and a service account refers to its namespace, which could not go while it stayed. The namespace's grants, its authentication policy and its variables go with the row.
The row is locked before anything is counted, so that a workflow pushed, a secret written or a service account created while the counts are read waits for this transaction and then finds the namespace gone, rather than landing in a namespace counted as empty.
func (*Wide) RemoveNamespaceAvatar ¶ added in v0.6.0
RemoveNamespaceAvatar removes a namespace's picture, and answers whether it had one. A namespace that does not exist is ErrNoNamespace, told apart from one with no picture, which removing changes nothing of.
func (*Wide) RemovePrincipal ¶ added in v0.3.0
RemovePrincipal removes a user, a group or a service account, and everything it holds with it: its credentials, tokens, sessions, enrolment codes, memberships and grants. A principal that owns a namespace is refused with ErrOwnsNamespace.
func (*Wide) RemoveServiceAccount ¶ added in v0.3.0
func (w *Wide) RemoveServiceAccount(ctx context.Context, namespace, name string) (ServiceAccount, error)
RemoveServiceAccount removes a service account and everything it holds, its tokens and its grants among them, and answers what it was. The built-in identity is ErrBuiltIn, one nobody created ErrNoPrincipal, and one a namespace's record names as owner ErrOwnsNamespace.
func (*Wide) RenameNamespace ¶ added in v0.6.0
RenameNamespace gives the namespace from the name to, and answers whether it changed anything: a rename to the name it has is none. "The rename is one transaction and carries everything at once."
The namespace's row is held first, and then the lock every creation of a login or a namespace takes, so that a name checked free here is still free when it is written. It is refused, in this order: ErrNoNamespace; ErrPersonalRename; *NameHeld where a login, a namespace or another namespace's former name holds to; and *RenameWaits while a run of it is going, a move to it or from it waits, or a runner not revoked narrows itself to it.
Then the principals of its service accounts are written under the new name, so that each service account, whose principal is made of its namespace's name and its own, finds its principal when the namespace's row changes; the row changes, its name and the names it held together, and every key naming it carries the change through (migration 0069); the columns naming one of its service accounts as text, or naming it with no key, are written; and the principals under the old name go, nothing referring to them any more. The audit log is not written: its caller records the rename.
func (*Wide) RequeueOf ¶
func (w *Wide) RequeueOf(ctx context.Context, namespace string, key agk.TaskID, row string) (int, error)
RequeueOf answers which dispatch of its key a row records, as graph.ShardState counts them.
A result names its unit of work by the key and its dispatch by the task_id, and the evaluator counts dispatches rather than holding rows: this is the one number between them, read the other way from TaskRow. A row that is not a dispatch of the key is answered ErrNoDispatch.
func (*Wide) Revocations ¶ added in v0.3.0
func (w *Wide) Revocations(ctx context.Context, namespace, workflow string, p access.Principal) ([]Revocation, error)
Revocations answers the grants of namespace revoked from p or from one of its groups, on the namespace or on workflow, newest first, as the audit log recorded each: RevokeAccess removes a grant rather than keeping it, and the log is where what it was stays. Where the principal, the scope or the role an entry records cannot be read as a grant, the entry is passed over, since what is asked is which grant gave something, and an entry that cannot say gave nothing anybody could name.
func (*Wide) Revoke ¶
func (w *Wide) Revoke(ctx context.Context, runner, by, why string, at time.Time, grace time.Duration) (Runner, error)
Revoke stops a runner taking anything new at once, and stops its credential being accepted at all once grace has passed, and answers the runner as it now stands.
"Revoking a credential never destroys work already done." Until the revocation plus the grace, ResultsAcceptedUntil, the runner is still heard at the heartbeat and told to drain, may publish the results of what it holds and hear stops, and redeems nothing; from then on every call it makes is refused, and the sweep declares lost whatever it still holds. The end of the grace is written as an instant, so that an installation changing its setting afterwards moves no grace already given. A runner already revoked is answered as it stands, since revoking it again would otherwise be a way of lengthening its grace, and one that is not there is ErrNoRunner.
func (*Wide) RevokeSessions ¶ added in v0.3.0
func (w *Wide) RevokeSessions(ctx context.Context, login string, hash []byte, at time.Time) (int, error)
RevokeSessions revokes a user's live sessions, or the one whose identifier hashes to hash where hash is given, and answers how many it revoked.
func (*Wide) RevokeToken ¶ added in v0.3.0
RevokeToken revokes one of a principal's tokens, and answers whether it was live until now. A token of another principal is ErrNoToken, so that revoking one by one names only one's own.
func (*Wide) Rewake ¶
func (w *Wide) Rewake(ctx context.Context, namespace string, run agk.RunID, version string, wake time.Time) error
Rewake sets the moment a run is due again, where nothing has written the run since it was read at version. The zero time is "nothing waits on the clock".
It is for a pass that decided nothing: its clock is all it has to write. A run written since it was read has been given its clock by whatever wrote it: a decision, or a loss the heartbeat declared or a runner reported, which writes the clock and not the sequence. Written over, that loss would never be heard, and a run waiting on the task it lost would wait for ever. Not the clock the pass read either, since a loss may set the very moment a result set before it.
func (*Wide) Rotate ¶
func (w *Wide) Rotate(ctx context.Context, ro Rotating, rotateAfter time.Duration, now time.Time) (Rotated, error)
Rotate gives a runner a new credential, for the one it holds and a signature by its key.
"The key proves the machine": the credential alone renews nothing, so a copy of it taken off a disk or a backup lasts until its rotate_by and no longer, while the host that holds the key keeps renewing. The new credential is accepted until now plus rotateAfter, which is how far "rotate_by moves". The one presented stays accepted until its own rotate_by or until the new one is first presented, whichever comes first, so that an answer lost on the way back locks nobody out: the runner rotates again with what it still holds, and the credential it never received is dropped. A runner therefore holds at most two, the one it last rotated with and the one that answered.
A revoked runner rotates nothing, in its grace or after it: its credential is ending, and renewing it would carry the runner past the grace it was given. A draining one rotates. A drain takes no credential away, and a drained runner "stays up", heartbeating for as long as it is left drained, which may be longer than its rotate_by: refused, it would be locked out at that instant and have to join again, and a drain would be a revocation that took a month.
The runner is locked while it is judged, so that two rotations at once cannot both keep the credential they presented: the second waits, and finds what the first left.
func (*Wide) Run ¶
Run reads one run for deciding.
It is on the installation door because the controller is the installation's: it is elected once and serves every namespace, and a notification carries "an identifier and nothing else", so which namespace a run belongs to is something this answers rather than something the caller knew.
func (*Wide) RunDurations ¶ added in v0.6.0
func (w *Wide) RunDurations(ctx context.Context, among []Workflow, b Buckets, bins int) ([]Bin, error)
RunDurations is the histogram of how long the runs of the workflows among that ended took, counted over the buckets b spans, in at most bins bins of one width from the shortest to the longest; fewer where fewer runs ended, and none where none did.
func (*Wide) RunStatistics ¶ added in v0.6.0
RunStatistics counts the runs of the workflows among, which the authorizer allowed, bucket by bucket. Every bucket is answered, those counting nothing included, oldest first.
func (*Wide) RunnerPoolNamed ¶
RunnerPoolNamed answers one.
func (*Wide) RunnerPools ¶
func (w *Wide) RunnerPools(ctx context.Context) ([]RunnerPool, error)
RunnerPools is the listing, ordered by name.
func (*Wide) Runs ¶
Runs lists the runs of the workflows given and of no others, newest first.
"with the failing and waiting runs surfaced first" is the console's ordering and not this one: what is ordered here is time, because a listing that reordered itself by state would be a listing whose second page overlapped its first. The surfacing is the client's to do over what it was given.
The second half of a listing, across namespaces or within one, given the workflows the authorizer allowed. None given reads nothing, rather than everything: the filter is the authorisation decision, and a missing one fails closed. There is no listing of one namespace's runs that skips the question, because "a deny wins at any scope" and a deny on one workflow is only in the answer where that workflow is in the question.
func (*Wide) SaveDecision ¶
SaveDecision writes one pass, or refuses it because the run has moved.
func (*Wide) ServiceAccount ¶ added in v0.3.0
ServiceAccount reads one, or answers ErrNoPrincipal.
func (*Wide) ServiceAccounts ¶ added in v0.3.0
ServiceAccounts answers a namespace's, ordered by name.
func (*Wide) ServiceAccountsIn ¶ added in v0.3.0
func (w *Wide) ServiceAccountsIn(ctx context.Context, namespaces []string) ([]ServiceAccount, error)
ServiceAccountsIn answers the service accounts of the namespaces named, the built-in identity of each among them, ordered by namespace and then by name: what an owner of those namespaces lists.
func (*Wide) SessionByHash ¶ added in v0.3.0
SessionByHash answers the session whose identifier hashes to hash, if it is live at now, with the type of the credential that opened it, whether that credential is a synced passkey, and whether its user administers the installation.
func (*Wide) SetAvatar ¶ added in v0.6.0
SetAvatar writes a user's photo, as the API re-encoded it, set at at, in place of any before it. A login no user holds is ErrNoPrincipal.
func (*Wide) SetBootstrapToken ¶ added in v0.3.0
SetBootstrapToken keeps the hash of the bootstrap token, as init does at every run from the token the installation's settings hold, and answers whether it changed. Once the token has ended it is ErrBootstrapEnded, and nothing is written.
func (*Wide) SetEmail ¶ added in v0.6.0
SetEmail writes the email address an administrator gives a user, the empty string removing it. A login no user holds is ErrNoPrincipal.
func (*Wide) SetGroup ¶
SetGroup records which concurrency group a run belongs to.
Stamped by the controller on the first pass that looks at the run, because the group is read out of the graph and whoever created the run does not read graphs.
func (*Wide) SetInstallationPolicy ¶ added in v0.3.0
SetInstallationPolicy writes the installation's, every setting of it. One with a setting missing is refused: the installation's policy is the one nothing is inherited from.
func (*Wide) SetNamespaceAvatar ¶ added in v0.6.0
SetNamespaceAvatar sets a namespace's picture, the PNG the API encoded, set at at. A namespace that does not exist is ErrNoNamespace.
func (*Wide) SetNamespacePolicy ¶ added in v0.3.0
func (w *Wide) SetNamespacePolicy(ctx context.Context, namespace string, p AuthPolicy, at time.Time) error
SetNamespacePolicy writes what a namespace tightens, replacing what it tightened before. A policy that sets nothing removes the namespace's, which then follows the installation's whole.
func (*Wide) SetOwner ¶ added in v0.3.0
SetOwner gives a namespace an owner, a principal that exists. A personal namespace is its user's, and handing it to anybody else is refused by the table.
func (*Wide) SetPassword ¶ added in v0.3.0
func (w *Wide) SetPassword(ctx context.Context, login, id, hash string, at time.Time) (Credential, bool, error)
SetPassword sets login's password to hash at at, and answers it as recorded and whether it replaced one. A password held is replaced in its row, which keeps its identifier, and so the sessions it opened, which its caller ends or keeps, and the TOTP generator beside it, which goes wherever the password's row goes; it is recorded as set at at and used by nobody since, as $defs/passwordCredential's created_at is "when the password was last set". The codes the one it replaces minted for agk login go, since whoever knew it may be who holds them, and the row they would have gone with stays. Where none is held, one is enrolled under id.
Its caller holds the user's row first (HoldUser), as every act on an account does, so that two settings at once take turns rather than both enrolling one.
func (*Wide) SetQuotas ¶ added in v0.3.0
SetQuotas writes a namespace's quotas whole: a zero MaxConcurrentTasks keeps the value it has, and any other zero, or a nil AllowedRunnerPools, bounds nothing.
func (*Wide) ShipChunk ¶
ShipChunk records what a shipment did to a log: the chunk, where it was taken, and the log as it now stands, which is was with the chunk counted in.
A chunk is recorded unless the log was already cut short before it arrived, since from then on nothing is written and a runner that went on shipping would otherwise grow the index a row per request. The task's row is given the log's URI the first time, which is what the purge finds a log by: a task whose result never came back still has its log swept with its run. Whoever follows the log is told on LogChannel, which PostgreSQL delivers once the chunk is committed.
func (*Wide) ShippedChunk ¶
ShippedChunk is one chunk of a log the index already holds, and false where it holds none.
func (*Wide) ShippingLog ¶
func (w *Wide) ShippingLog(ctx context.Context, clear string, task agk.TaskID, runner string) (TaskLog, error)
ShippingLog finds the log a shipment writes to, and holds it until the transaction ends.
The grant says which dispatch, and it is found by its hash and the row its text names, as a redemption finds it. The body's key has to be the one the dispatch is of: "a shipment whose body and grant name different tasks is refused, rather than written under whichever of the two was read first", and it is refused as a grant that opens nothing, as a redemption is.
The grant's expiry is not held to, unlike at a redemption. It is the task's deadline, and the last chunk of a task stopped at its deadline arrives after it: refused then, the log of every task that ran out of time would lose the lines that say why. What a grant past its expiry could open is what the runner the task is bound to could open anyway, since the binding is what is checked, and a grant lifted from a queue opens nothing without that runner's credential.
The task is the runner's when a redemption bound it to it, whatever state the task is in since: a cancelled task's container is still stopping and its last lines still coming, and a task declared lost may have been only cut off, which the host then finishes. A runner draining, or revoked and in its grace, is finishing what it holds, which is what a drain and a grace are for, and shipping its log is part of finishing. A task nobody bound, or somebody else, is ErrTaskHeld.
func (*Wide) ShutEnrolmentCode ¶ added in v0.3.0
func (w *Wide) ShutEnrolmentCode(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, string, error)
ShutEnrolmentCode answers the code whose value hashes to hash whatever its state, and why it opens nothing at now: CodeUsed, CodeReplaced, CodeLapsed, CodeEnrolled for a link whose user holds a credential already, CodeBootstrapEnded for a first administrator's link the end of the bootstrap revoked, which it revokes at the moment it ends, or for a recovery code of the bootstrap token that has ended, or the empty string for one open still. It is ErrNoEnrolmentCode where no code of that value was issued, or its user was removed with it. What a refused sign-in records, which names the account a code was issued for and why it opened nothing, and never the code.
func (*Wide) Slots ¶
Slots is how many more tasks this namespace may have in flight.
"max_concurrent_tasks: Caps how much of the runner fleet one namespace can hold at once, so a fan-out of ten thousand items cannot starve everyone else." What counts against it is a task that holds a runner or is on its way to one, which is the four states between being decided and being over. The keys ending are left out: the caller is ending them in the decision it has yet to write.
func (*Wide) StartTOTP ¶ added in v0.3.0
func (w *Wide) StartTOTP(ctx context.Context, e TOTPEnrolment) error
StartTOTP keeps a generator started, in place of the one its user had started before, whose secret was shown and may never have reached an application.
func (*Wide) StepHours ¶ added in v0.6.0
func (w *Wide) StepHours(ctx context.Context, of Workflow, from, to time.Time) (map[string][]Percentiles, error)
StepHours is the median of how long each step of the one workflow of ran, by the weekday and the hour of the day its attempts were dispatched, in UTC, over the runs created from from to to: a cell for every hour of the week, Monday at midnight first, and not Taken where none ran.
func (*Wide) StepStatistics ¶ added in v0.6.0
func (w *Wide) StepStatistics(ctx context.Context, of Workflow, b Buckets) (map[string][]StepBucket, error)
StepStatistics counts the steps of the one workflow of, which the authorizer allowed, bucket by bucket, answering each step whose tasks the buckets reach. Every bucket of a step is answered, those counting nothing included, oldest first.
func (*Wide) StopReport ¶
func (w *Wide) StopReport(ctx context.Context, namespace string, key agk.TaskID, row, runner string, r Stopped) (bool, error)
StopReport writes onto one dispatch that the controller stopped what its runner reported of it: the exit code its container exited with, where its log went and what it cost. It answers whether a row took it.
CancelTasks and EndTasks end a run's tasks in the pass that ends the run, before any container has exited, so the rows they end carry no code; the runner's report comes later, to a run with nothing left to decide. "A timed_out or cancelled task carries an exit code wherever a container ran" all the same, and this is where it lands, beside the log and the usage a decision would have written had the task still been in flight; the decisions written after it keep them. A task the evaluator stopped as superseded or sibling_failed while its run goes on is ended the same way, in the pass that sends the stop, and its report comes to a task that is over: the evaluator takes the code of it and a decision writes it, so what lands here is the log and the usage of a report it took no code from, and the code of one that came after the run ended. Only on a row that is stopped and has no code yet, so an ending is written once; only on the dispatch named by its row and its key, as HeldBy compares them; and only from the runner the dispatch is bound to. What the row already says of when it started and of its log is kept, and when it finished is the moment the controller ended it, which stays.
func (*Wide) StorageOf ¶ added in v0.6.0
StorageOf is the storage name of the namespace named name, as NS.Storage answers it.
func (*Wide) Suspend ¶ added in v0.3.0
Suspend suspends login for reason, and answers whether they were not suspended already: one suspended already keeps the reason it was suspended for, which the enrolment that answers it is the one to lift. Its caller holds the user's row (HoldUser), as every act on an account does.
func (*Wide) TOTPEnrolmentOf ¶ added in v0.3.0
func (w *Wide) TOTPEnrolmentOf(ctx context.Context, login string, now time.Time) (TOTPEnrolment, error)
TOTPEnrolmentOf answers the generator login started, if it is still waiting at now.
func (*Wide) TOTPUsed ¶ added in v0.3.0
TOTPUsed records a TOTP code accepted at step, and when: the step is kept, so that no code of it or of a step before it is accepted again. One at or before the step recorded is ErrTOTPSpent and nothing is recorded, checked in the statement that writes it, so that of two sign-ins with one code, verified against one reading, the second is still refused.
func (*Wide) TakeChallenge ¶ added in v0.3.0
TakeChallenge answers the challenge value names, if it is open at now, and removes it in the same statement: of two verifications presenting it at once, one takes it and the other is answered ErrNoChallenge.
func (*Wide) TakeExchangeCode ¶ added in v0.3.0
func (w *Wide) TakeExchangeCode(ctx context.Context, hash []byte, now time.Time) (ExchangeCode, error)
TakeExchangeCode answers the code whose value hashes to hash, if it is open at now, and removes it in the same statement, whatever the caller then makes of it: of two exchanges presenting it at once, one takes it and the other is answered ErrNoExchangeCode, and a code presented with a verifier that is not its own is spent all the same.
func (*Wide) TaskRow ¶
TaskRow is the identifier a task's own row is keyed by: the row of the latest dispatch of the key, which is the one a decision has just planned.
Not the idempotency key. The key says which unit of work this is and is derived from what makes it that; the row says which record, and it is what a grant names inside its own text and what a log is addressed by. The two are separate on purpose: one is a statement about the work and the other is a handle on a row, and a key requeued after a loss has a row for every dispatch.
func (*Wide) TellAdministrators ¶ added in v0.3.0
func (w *Wide) TellAdministrators(ctx context.Context, login string, at time.Time) ([]string, error)
TellAdministrators writes BreakGlassRecovery, about the recovery code the break-glass path issued the administrator login at at, to every administrator, login among them, and answers who was told, by login. Every one, suspended or holding no credential included, since each may be the one who comes back to read it, and the one recovered first of all: if they did not ask for it, whoever holds the host did.
It is written in the transaction that issues the code, so that no break-glass code commits untold, after the code's row and before the audit entry: the code's row takes the recovered user's, and each notification its recipient's principal, which is the order removing an administrator takes them in, every administrator's user row before the principal it deletes.
func (*Wide) TellOwners ¶ added in v0.3.0
TellOwners writes what NS.TellOwners does, in the namespace the grant's scope names, for a grant the installation's handle writes, as Wide.GrantAccess does.
func (*Wide) TellOwnersIn ¶ added in v0.3.0
TellOwnersIn writes AdminAccessWidened in namespace, as NS.TellOwners writes it in its handle's, from a transaction across the installation: a group's membership reaches every namespace its grants and denies are in, and an administrator putting somebody in a group widens access in each of those where it holds a role, as taking themselves out of one, or removing one they are in, widens their own in each of those where it holds a deny.
func (*Wide) TellPasskeyRefused ¶ added in v0.3.0
func (w *Wide) TellPasskeyRefused(ctx context.Context, login, credential string, at time.Time) error
TellPasskeyRefused tells login, in their GET /api/v1/me, that a sign-in with their passkey credential was refused at at because its signature counter did not move forward: PasskeyCounterRefused. The passkey is named by its credential ID and not referred to, so that removing it, which is what its user may do on reading this, leaves what they were told.
func (*Wide) Token ¶ added in v0.3.0
Token answers one token by its identifier, revoked and expired ones included, or ErrNoToken: whose it is decides who may revoke it.
func (*Wide) TokenByHash ¶ added in v0.3.0
TokenByHash answers the token whose value hashes to hash, if it is neither revoked nor expired at now, and its principal is not a suspended user.
func (*Wide) TokensOf ¶ added in v0.3.0
func (w *Wide) TokensOf(ctx context.Context, principal string, namespaces []string, now time.Time) ([]APIToken, error)
TokensOf answers the tokens of a principal, and of the service accounts of the namespaces named, that are still accepted at now, newest first: what a listing shows, since "an expired or revoked token is gone from the list". A suspended user's are gone from it too, since none of them opens anything while the suspension lasts.
func (*Wide) TouchSession ¶ added in v0.3.0
TouchSession moves the idle expiry of a session live at now to until. One that is not live stays as it is, so that a request arriving late opens nothing again.
func (*Wide) Trace ¶
Trace reads a run and every dispatch of its tasks, in the order a person reads them.
func (*Wide) Tree ¶
Tree reads the tree of one version and nothing else, for a redemption.
Through the installation door because a runner works for several namespaces and learns which one a task belongs to from the grant, and narrowed to the one column because the redemption has no use for the rest: the document a graph is rebuilt from is the controller's business. It answers ErrNoVersion for a commit nobody recorded and ErrNoTree for one recorded without its tree, so that neither becomes an empty directory.
func (*Wide) Unarmed ¶ added in v0.5.0
Unarmed lists the workflows whose default branch's head is not what they have armed, across every namespace: those pushed before v0.5.0, which arms nothing at the upgrade, and any whose arming failed. The leading controller arms each at the start of its term. A workflow holding no git ref is left out, since its head is whatever version a tree push recorded last and the tree push arms it itself.
func (*Wide) Undelivered ¶
Undelivered names the events nobody has been told about.
In the order they happened, because a person told that a run completed before being told it failed has been told two true things in the order that makes the second one confusing.
func (*Wide) Unpublished ¶
func (w *Wide) Unpublished(ctx context.Context, namespace string, run agk.RunID) ([]agk.TaskID, error)
Unpublished names the tasks of one run whose messages never went.
Pending or dispatched, because a task is dispatched in the evaluator's state the moment it is planned: "recording the dispatch is what fixes the task's deadline, because the deadline runs from the moment the work became somebody's". A task that has reached running or beyond was plainly delivered, whatever the stamp says.
func (*Wide) UpdateProfile ¶ added in v0.6.0
UpdateProfile writes what a user says of themself: their profile, every field of it, the empty string clearing one. A login no user holds is ErrNoPrincipal.
func (*Wide) UpdateUser ¶ added in v0.3.0
UpdateUser writes what an administrator and the authentication policy change of a user: whether they administer, and whether they are suspended, and why. The login never changes, since it is also the name of their personal namespace; the email address is written on its own (SetEmail); and the profile and the photo are left as they are, being the user's own to write (UpdateProfile, SetAvatar).
func (*Wide) UseEnrolmentCode ¶ added in v0.3.0
func (w *Wide) UseEnrolmentCode(ctx context.Context, hash []byte, now time.Time) (EnrolmentCode, error)
UseEnrolmentCode spends an open code at now and answers it. Of two uses at once, one spends it and the other is answered ErrNoEnrolmentCode.
func (*Wide) UserVerificationRequired ¶ added in v0.3.0
UserVerificationRequired says whether any authentication policy of the installation requires user verification, its own or a namespace's: what an assertion's options ask for, since they are issued before the passkey names whose policy applies.
func (*Wide) UsersUnderPolicy ¶ added in v0.3.0
func (w *Wide) UsersUnderPolicy(ctx context.Context, namespace string, now time.Time) ([]string, error)
UsersUnderPolicy answers the logins of the users a namespace's authentication policy applies to, ordered by login: those holding a grant carrying a role in it at now, their own or one of their groups', on the namespace or on one of its workflows, since "a namespace's policy applies at sign-in, to every account holding a grant in the namespace". A deny alone is not a grant here, as it is nowhere else.
func (*Wide) VerifyAuditLog ¶
VerifyAuditLog checks the whole audit log from its first entry, and answers the first *audit.Break.
Beside each entry following the one before it, the last entry has to be the head of the chain, which an append moves and nothing else can: an entry removed from the end leaves a chain that holds up to where it stops, and a head that is further on.
func (*Wide) WakeCaller ¶ added in v0.5.0
WakeCaller wakes the run whose call started run, where one did and it has not ended: the run it called has ended, and the step waiting on it has its answer. In the transaction that writes the ending, so that the caller is told of an ending that is written and of no other.
func (*Wide) Within ¶ added in v0.5.0
func (w *Wide) Within(ctx context.Context, namespace string, fn func(context.Context, *NS) error) error
Within runs fn over this transaction as In would in namespace, the installation's scope set aside meanwhile and back once fn has returned: for a change a request makes in its own namespace inside a transaction that reaches across the installation for another reason, so that the change reads and writes what a handle on that namespace reaches and no more. An error fn answers ends the transaction, and the scope is left as it is.
func (*Wide) Workflows ¶
Workflows are every workflow there is, narrowed to one namespace or one name where either is given, in order.
It is the first half of a listing across namespaces: what the authorizer is asked about, one workflow at a time, since a permission is held on a whole namespace or on a single workflow and both are answered by asking about the workflow.
type Widening ¶ added in v0.3.0
type Widening struct {
// Grant is the grant written, the deny revoked, or the group's grant or deny a membership
// brought or took away, kept whole rather than referred to, since it may be revoked before its
// reader comes to read it, and what they are told is what was done.
Grant access.Grant
// Act is what was done, one of the Act constants, and By who did it, left out of those told,
// since telling somebody what they have just done tells them nothing.
Act string
By string
// Member is the user put in the group, on ActJoinedGroup alone.
Member string
// At is when it was done, from which the 90 days it is kept are counted.
At time.Time
}
Widening is what an administrator did in a namespace that its owners are told of.
type Workflow ¶
Workflow is one workflow, named as the installation names it: by its namespace and its name.
type WorkflowRecord ¶ added in v0.4.0
type WorkflowRecord struct {
Namespace string
Name string
DefaultBranch string
// Protected is the default branch's protection, which is the repository's: only the default
// branch is ever protected.
Protected bool
CreatedAt time.Time
// CreatedBy is who created it by POST /api/v1/{ns}/workflows, empty for a workflow from
// before v0.4.0 or one a tree push created.
CreatedBy string
// Head is the commit the default branch points at, empty while it is unborn.
Head string
}
WorkflowRecord is a workflow's repository as the API answers it: its name, its default branch and whether that branch is protected, who created it and when, and the commit its default branch points at. Its labels are not read here: they are what the default version's entry point writes, which the API reads from that version.
type Writing ¶ added in v0.3.0
type Writing struct {
// contains filtered or unexported fields
}
Writing is one write Uploading recorded, for NotWritten to let go of where its bytes never arrived.
type Written ¶
type Written struct {
// Key is the physical key the bytes are under, <namespace>/sha256/<digest>.
Key string
// ExpiresAt is when the reference stops being fetchable, capped by the namespace:
// "retain is capped by the namespace quota and cannot exceed it". The zero time is a reference
// nothing bounds, kept for ever.
ExpiresAt time.Time
// Fetches is what is left of the budget, zero where there is none.
Fetches int
// Status is what the reference is, which is Live for anything just written and
// whatever it had become for a reference that was already there.
Status Status
// New is false where this exact reference was already recorded, which a retried
// task and a replay that recomputes identical bytes both produce.
New bool
// MustWriteBytes is a sweep was about to delete this object, so write the bytes
// again before trusting the reference. See the collection protocol in purge.go: the
// reference is safe either way, and what is not safe is assuming the object survived
// the sweep that had already claimed it.
MustWriteBytes bool
}
Written is what recording a reference settled.
Source Files
¶
- access.go
- activity.go
- artifacts.go
- audit.go
- calls.go
- controller.go
- credentials.go
- db.go
- delete.go
- doc.go
- envelopes.go
- events.go
- exchange.go
- grants.go
- images.go
- keepalives.go
- live.go
- logs.go
- logstream.go
- memo.go
- metrics.go
- migrate.go
- move.go
- names.go
- namespaces.go
- notifications.go
- orphans.go
- packs.go
- passkeys.go
- policy.go
- pools.go
- principals.go
- purge.go
- reading.go
- refs.go
- rename.go
- role.go
- runners.go
- runs.go
- schedule.go
- secret_values.go
- secrets.go
- stats.go
- tokens.go
- told.go
- trace.go
- triggers.go
- unrecorded.go
- uploads.go
- variables.go
- versions.go
- webhooks.go
- workflows.go