packops

package
v1.0.0-rc.4 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package packops orchestrates pack verbs (add, apply, status, remove) over the standalone kind managers (skillsync, agentsync, contexts, wiring). There is still no pack write path of its own: a pack expands into calls against the engines that own every write, and this package only owns the expansion. The CLI and the REST layer both drive these functions; rendering and exit codes stay with each caller.

Index

Constants

View Source
const SchemaVersion = 1

SchemaVersion versions every pack document (Article X).

Variables

View Source
var (
	// ErrNoManifest marks a repository without a gridctl-pack.yaml at
	// its root.
	ErrNoManifest = errors.New("no pack manifest found")
	// ErrNotImported marks a pack name with no record in the import
	// lockfile.
	ErrNotImported = errors.New("pack is not imported")
	// ErrNameCollision marks a pack name claimed by more than one
	// imported source; operations must refuse rather than pick one.
	ErrNameCollision = errors.New("pack name is claimed by multiple sources")
	// ErrLockStale marks a --locked add whose pack lock is missing or
	// does not match the manifest. Nothing is written.
	ErrLockStale = errors.New("pack lock is stale")
	// ErrLockFlags marks --locked and --ignore-lock used together.
	ErrLockFlags = errors.New("locked and ignore-lock are mutually exclusive")
	// ErrBoostersAttached marks removal of a base that still has boosters.
	ErrBoostersAttached = errors.New("pack has attached boosters")
	// ErrBaseNotAdded marks a booster whose base pack is not imported.
	ErrBaseNotAdded = errors.New("base pack is not added")
	// ErrPackRequires marks a pack whose requires.gridctl the running
	// gridctl does not satisfy, or whose constraint does not parse.
	// Nothing is imported or projected.
	ErrPackRequires = errors.New("pack gridctl requirement failed")
)

Sentinel errors callers branch on with errors.Is; the user-facing prose rides on the concrete error unchanged.

Functions

func ComposedStackPath

func ComposedStackPath(home, packName string) string

ComposedStackPath is ~/.gridctl/packs/<base>/composed/stack.yaml.

func IsPackOwnedPath

func IsPackOwnedPath(home, pack, path string) bool

IsPackOwnedPath reports whether path lies under the pack's checkout root. This is a path heuristic: the daemon state file records StackFile and no pack owner, so a hand-started daemon whose stack file sits in that directory is treated as pack-owned.

func LoadLockedPack

func LoadLockedPack(name string) (*skills.LockedPack, error)

LoadLockedPack finds a pack's record in the default import lockfile.

func LockedPackOverride

func LockedPackOverride(home, lockPath, stackFile string) (pack, path string, ok bool)

LockedPackOverride reports the override path when stackFile is under a locked pack checkout. The lock file is read from lockPath.

func OverridePath

func OverridePath(home, pack string) string

OverridePath is ~/.gridctl/overrides/<pack>.yaml under home. The file is optional; its absence leaves the pinned checkout unchanged.

func PackCheckoutDir

func PackCheckoutDir(home, pack, sha string) string

PackCheckoutDir is the pinned checkout for one commit.

func PackCheckoutRoot

func PackCheckoutRoot(home, pack string) string

PackCheckoutRoot is ~/.gridctl/packs/<pack> under home.

func PinnedStackPath

func PinnedStackPath(st *skills.LockedStack) string

PinnedStackPath is the absolute path of a pack's pinned stack file.

func TallyRows

func TallyRows(rows []Row) (applied, failed int)

TallyRows counts clean rows vs rows needing attention.

Types

type AddDoc

type AddDoc struct {
	SchemaVersion  int                                         `json:"schema_version"`
	DryRun         bool                                        `json:"dry_run,omitempty"`
	Pack           string                                      `json:"pack"`
	Skills         []string                                    `json:"skills"`
	Agents         []string                                    `json:"agents"`
	Rules          []string                                    `json:"rules,omitempty"`
	Wiring         bool                                        `json:"wiring"`
	Unresolved     []string                                    `json:"unresolved,omitempty"`
	Skipped        []string                                    `json:"skipped,omitempty"`
	Warnings       []string                                    `json:"warnings,omitempty"`
	Variables      map[string]skills.LockedVariableDeclaration `json:"variables,omitempty"`
	UnmetVariables []VariableRequirement                       `json:"unmet_variables,omitempty"`
	Stack          *StackSummary                               `json:"stack,omitempty"`
	Sources        []SourceSummary                             `json:"sources,omitempty"`
	Lock           *LockSummary                                `json:"lock,omitempty"`
}

AddDoc is the machine-readable pack add document.

type AddOptions

type AddOptions struct {
	Repo   string
	Ref    string
	Path   string
	Trust  bool
	DryRun bool
	// BlockOnFindings refuses the whole import with a *FindingsError
	// before any write when the resolved selection carries security
	// findings and Trust is false. The CLI leaves it false (partial
	// import with per-resource skips, its documented contract); the REST
	// layer sets it so a 409 can never follow a half-done import.
	BlockOnFindings bool
	// Auth authenticates the pack repository clone. A token or vault
	// reference here never applies to an external source. An ssh-key
	// path is reused for SSH sources that resolved no other auth.
	Auth skills.AuthConfig
	// SourceAuth is an explicit per-source override, keyed by source name.
	// A present key wins even when the value is zero. Omitted keys fall
	// through to stored member auth, the manifest, then ambient.
	SourceAuth map[string]skills.AuthConfig
	// Resolver expands manifest and stored credential references. Nil means
	// a credential_ref on a source is an error for that source.
	Resolver skills.CredentialResolver
	// Locked refuses a stale or missing pack lock before any source clone
	// or write. IgnoreLock reads the lock for reporting and resolves refs.
	Locked     bool
	IgnoreLock bool
	// contains filtered or unexported fields
}

AddOptions parameterizes a pack import.

type AddResult

type AddResult struct {
	Doc   AddDoc
	Notes []string
}

AddResult pairs the document with progress notes the CLI prints in order (rule updates, fragments-mode migration). Notes are caller-facing prose, not part of the versioned document.

type ApplyDoc

type ApplyDoc struct {
	SchemaVersion int    `json:"schema_version"`
	Pack          string `json:"pack"`
	DryRun        bool   `json:"dry_run,omitempty"`
	Applied       int    `json:"applied"`
	Total         int    `json:"total"`
	Rows          []Row  `json:"rows"`
}

ApplyDoc is the machine-readable apply document.

type ApplyOptions

type ApplyOptions struct {
	Force  bool
	DryRun bool
	// Clients restricts wiring to these client slugs.
	Clients []string
	// Port is the gateway port passed to the stack launcher. Zero means
	// the launcher's default (the CLI passes 8180).
	Port int
	// PortSet is true when the caller passed --port. A booster apply ignores
	// it while the base daemon is running and prints a note.
	PortSet bool
}

ApplyOptions parameterizes a pack projection, mirroring the CLI flags one to one (--force, --dry-run, --clients, --port).

type Counts

type Counts struct {
	Skills int  `json:"skills"`
	Agents int  `json:"agents"`
	Rules  int  `json:"rules"`
	Wiring bool `json:"wiring"`
	// Stack is true when the pack carries a resolved stack record.
	// omitempty keeps packs without a stack on the previous JSON shape.
	Stack bool `json:"stack,omitempty"`
	// Sources is the number of pinned external sources. omitempty keeps
	// packs without sources on the previous JSON shape.
	Sources int `json:"sources,omitempty"`
}

Counts summarizes a pack's resolved selection per kind.

type FindingsError

type FindingsError struct {
	Pack      string
	Resources []PreviewResource
}

FindingsError blocks an import whose resolved selection carries security findings and no trust acknowledgment. It is returned before any write, so a refusal never follows a half-done import.

func (*FindingsError) Error

func (e *FindingsError) Error() string

type LaunchOptions

type LaunchOptions struct {
	StackPath    string
	Port         int
	Replace      bool
	OverridePath string
}

LaunchOptions is one pack-stack deploy.

type LaunchResult

type LaunchResult struct {
	StackName string
	Port      int
}

LaunchResult is the daemon a launch left running.

type LockDoc

type LockDoc struct {
	SchemaVersion int                       `json:"schema_version"`
	Pack          string                    `json:"pack"`
	Path          string                    `json:"path"`
	Status        string                    `json:"status"`
	Reason        string                    `json:"reason,omitempty"`
	Digest        string                    `json:"digest,omitempty"`
	Sources       []LockSourceDoc           `json:"sources,omitempty"`
	Extends       map[string]LockExtendsDoc `json:"extends,omitempty"`
	Warnings      []string                  `json:"warnings,omitempty"`
}

LockDoc is the machine-readable pack lock document.

func Lock

func Lock(ctx context.Context, opts LockOptions) (*LockDoc, error)

Lock writes gridctl-pack.lock.yaml, or with Check compares it and writes nothing. Check does not clone. A source that fails to resolve leaves the file unwritten and sets status unresolved.

type LockExtendsDoc

type LockExtendsDoc struct {
	Repo   string `json:"repo"`
	Commit string `json:"commit"`
}

LockExtendsDoc is one base pack recorded in a pack lock document.

type LockOptions

type LockOptions struct {
	Dir        string
	Check      bool
	Auth       skills.AuthConfig
	SourceAuth map[string]skills.AuthConfig
	Resolver   skills.CredentialResolver
	// LockPath is the import lockfile used for stored auth and the extends
	// entry. Empty means the HOME-derived default.
	LockPath string
}

LockOptions parameterizes gridctl pack lock.

type LockSourceDoc

type LockSourceDoc struct {
	Name   string `json:"name"`
	Repo   string `json:"repo"`
	Ref    string `json:"ref,omitempty"`
	Commit string `json:"commit,omitempty"`
	Error  string `json:"error,omitempty"`
}

LockSourceDoc is one source in a pack lock document.

type LockSummary

type LockSummary struct {
	State  string   `json:"state"`
	Path   string   `json:"path,omitempty"`
	Digest string   `json:"digest,omitempty"`
	Reason string   `json:"reason,omitempty"`
	Notes  []string `json:"notes,omitempty"`
}

LockSummary is the pack-lock state on an add or preview document.

type Managers

type Managers struct {
	Skills   *skillsync.Manager
	Agents   *agentsync.Manager
	Wiring   *wiring.Manager
	Contexts *contexts.Manager
	Home     string
	// LockPath overrides the import lockfile path (skills.lock.yaml).
	// Empty means the HOME-derived default. Callers that inject a custom
	// lockfile path into their importer (the API server) must set the
	// same path here, or the importer and the pack record would write
	// two different files.
	LockPath string
	// Launcher deploys a pack-carried stack. Nil means this interface
	// cannot start a gateway (the REST server in this release).
	Launcher StackLauncher
	// StoredVariables reports vault keys. available is false when the
	// store cannot be read (locked or unset); the apply gate then falls
	// through to the loader instead of prompting.
	StoredVariables func() (keys map[string]bool, available bool)
}

Managers bundles the kind managers pack verbs orchestrate.

func (*Managers) Add

func (m *Managers) Add(ctx context.Context, imp *skills.Importer, opts AddOptions) (*AddResult, error)

Add clones, resolves the manifest selection, and imports.

func (*Managers) Apply

func (m *Managers) Apply(ctx context.Context, name string, opts ApplyOptions) (*ApplyDoc, error)

Apply projects one pack across every kind it selects. Apply is additive and never transactional: each resource succeeds or skips independently, and per-resource outcomes become rows, not errors.

func (*Managers) LoadLockedPack

func (m *Managers) LoadLockedPack(name string) (*skills.LockedPack, error)

LoadLockedPack finds a pack's record in this engine's lockfile.

func (*Managers) Remove

func (m *Managers) Remove(ctx context.Context, imp *skills.Importer, name string, opts RemoveOptions) (*RemoveDoc, error)

Remove cascades one pack's removal in dependency order: pack-tagged projections are unsynced, pack-tagged wiring records removed through the ownership manager, then the registry entries and the pack record itself. A drifted resource is kept unless forced; the trimmed pack record stays truthful about what remains.

func (*Managers) Statuses

func (m *Managers) Statuses(ctx context.Context, opts StatusOptions) ([]PackStatus, error)

Statuses reports the state matrix for one or all imported packs, sorted by pack name. Skill, agent, and wiring rows come from the kind managers' per-client statuses; rule rows report per-client projection state from the context engine (pack-tagged lock entries joined with per-fragment status), falling back to a store-presence row for rules that were imported but never projected.

type Origin

type Origin struct {
	Source    string    `json:"source"`
	Repo      string    `json:"repo"`
	Ref       string    `json:"ref,omitempty"`
	CommitSHA string    `json:"commit_sha,omitempty"`
	FetchedAt time.Time `json:"fetched_at,omitempty"`
}

Origin identifies where a pack was imported from, straight off its parent lockfile source.

type PackInfo

type PackInfo struct {
	Name        string   `json:"name"`
	Version     string   `json:"version,omitempty"`
	Description string   `json:"description,omitempty"`
	Author      string   `json:"author,omitempty"`
	Origin      Origin   `json:"origin"`
	Counts      Counts   `json:"counts"`
	Unresolved  []string `json:"unresolved,omitempty"`
	// Applied reports whether any per-client projection exists: an
	// imported-but-never-applied pack is registry-only, and list views
	// surface that as attention rather than reading healthy.
	Applied bool `json:"applied"`
	// Collision marks a pack name claimed by more than one source; the
	// listed repos disambiguate. Detail fetches for a colliding name
	// refuse instead of picking one.
	Collision      bool            `json:"collision,omitempty"`
	CollisionRepos []string        `json:"collision_repos,omitempty"`
	Sources        []SourceSummary `json:"sources,omitempty"`
	// Extends is the base pack a booster composes onto.
	Extends string `json:"extends,omitempty"`
}

PackInfo is the identity half of a pack status: everything a list view needs without the per-resource rows.

type PackRuleFile

type PackRuleFile struct {
	Name string
	Path string // absolute path on disk in the clone
	// Rel is the path within the pack repo, recorded as provenance so a
	// later install can name where the rule came from. Clone paths are
	// temporary and must never be persisted.
	Rel string
}

PackRuleFile is one discovered rule fragment in a pack repo.

type PackStatus

type PackStatus struct {
	Info           PackInfo `json:"info"`
	Rows           []Row    `json:"rows"`
	NeedsAttention bool     `json:"needs_attention"`
}

PackStatus is one pack's identity plus its per-resource state rows.

type PreviewOptions

type PreviewOptions struct {
	Repo string
	Ref  string
	Path string
	// Auth authenticates the pack repository clone. A token here never
	// applies to an external source.
	Auth skills.AuthConfig
	// SourceAuth is an explicit per-source override, keyed by source name.
	SourceAuth map[string]skills.AuthConfig
	// LockPath is the import lockfile used to reuse stored member auth.
	// Empty means the HOME-derived default.
	LockPath string
	// Resolver expands manifest and stored credential references.
	Resolver skills.CredentialResolver
	// Locked and IgnoreLock match pack add. Preview honors a matching lock
	// so the review step matches the import.
	Locked     bool
	IgnoreLock bool
}

PreviewOptions parameterizes a read-only pack resolution.

type PreviewResource

type PreviewResource struct {
	Kind     string                   `json:"kind"`
	Name     string                   `json:"name"`
	Findings []skills.SecurityFinding `json:"findings,omitempty"`
	// Blocking mirrors the import gate exactly: body findings always
	// block; supporting-file findings block only at danger severity.
	// Non-blocking findings stay visible without forcing a trust grant.
	Blocking bool `json:"blocking,omitempty"`
	// Source is the external source name. Empty for the pack repository.
	Source string `json:"source,omitempty"`
}

PreviewResource is one resolved resource with its scan findings.

type PreviewResult

type PreviewResult struct {
	Pack        string            `json:"pack"`
	Version     string            `json:"version,omitempty"`
	Description string            `json:"description,omitempty"`
	Author      string            `json:"author,omitempty"`
	Wiring      bool              `json:"wiring"`
	Clients     []string          `json:"clients,omitempty"`
	Skills      []PreviewResource `json:"skills"`
	Agents      []PreviewResource `json:"agents"`
	Rules       []PreviewResource `json:"rules"`
	Unresolved  []string          `json:"unresolved,omitempty"`
	Warnings    []string          `json:"warnings,omitempty"`
	Stack       *StackSummary     `json:"stack,omitempty"`
	Sources     []SourceSummary   `json:"sources,omitempty"`
	Lock        *LockSummary      `json:"lock,omitempty"`
}

PreviewResult is a pack manifest resolved against its repository, with nothing written: what an import would select, name by name, and which resources carry security findings.

func Preview

func Preview(ctx context.Context, opts PreviewOptions) (*PreviewResult, error)

Preview clones the repository, parses the pack manifest, and resolves the selection with scan findings, writing nothing.

type RemoveDoc

type RemoveDoc struct {
	SchemaVersion int      `json:"schema_version"`
	Pack          string   `json:"pack"`
	DryRun        bool     `json:"dry_run,omitempty"`
	Rows          []Row    `json:"rows"`
	Kept          []string `json:"kept,omitempty"`
}

RemoveDoc is the machine-readable remove document.

type RemoveOptions

type RemoveOptions struct {
	Force  bool
	DryRun bool
	// GatewayPort feeds the wiring status probe used to find pack-tagged
	// wiring records.
	GatewayPort int
}

RemoveOptions parameterizes a cascade removal.

type Row

type Row struct {
	Kind        string `json:"kind"`
	Name        string `json:"name"`
	Client      string `json:"client,omitempty"`
	Action      string `json:"action,omitempty"`
	State       string `json:"state,omitempty"`
	Detail      string `json:"detail,omitempty"`
	Remediation string `json:"remediation,omitempty"`
}

Row is one resource line in pack output.

type SourceSummary

type SourceSummary struct {
	Name      string   `json:"name"`
	Repo      string   `json:"repo"`
	Ref       string   `json:"ref,omitempty"`
	CommitSHA string   `json:"commit_sha,omitempty"`
	Skills    []string `json:"skills"`
	Agents    []string `json:"agents"`
	Error     string   `json:"error,omitempty"`
}

SourceSummary is one external source in an add, preview, or status document.

type StackLauncher

type StackLauncher interface {
	// Launch deploys the stack at StackPath as a background daemon and
	// returns the port it listens on. Replace stops a running daemon
	// with the same stack name first.
	Launch(ctx context.Context, opts LaunchOptions) (LaunchResult, error)
	// Stop stops the daemon named by stackName and removes its
	// containers. It must only be called for a daemon whose state file
	// StackFile is under the pack checkout directory.
	Stop(ctx context.Context, stackName string) error
	// Reload asks a running daemon to re-read its stack file. Composition
	// uses it only when that file is already the composed path.
	Reload(ctx context.Context, stackName string) error
}

StackLauncher deploys and stops a pack-carried stack. The CLI supplies it; the REST server leaves it nil.

type StackSummary

type StackSummary struct {
	Path     string `json:"path"`
	Name     string `json:"name"`
	Servers  int    `json:"servers"`
	Fragment bool   `json:"fragment,omitempty"`
	Extends  string `json:"extends,omitempty"`
}

StackSummary is the carried stack as add and preview report it.

type StatusOptions

type StatusOptions struct {
	// Pack restricts the report to one pack; empty means all.
	Pack string
	// GatewayPort feeds the wiring status probe (the caller resolves it:
	// the CLI from running state, the API server from its own listener).
	GatewayPort int
}

StatusOptions parameterizes a status pass.

type VariableRequirement

type VariableRequirement struct {
	Key         string `json:"key"`
	Type        string `json:"type"`
	Secret      bool   `json:"secret"`
	Description string `json:"description,omitempty"`
	Docs        string `json:"docs,omitempty"`
	Command     string `json:"command"`
}

VariableRequirement is a value-free prerequisite reported after import.

func UnmetVariables

func UnmetVariables(declarations map[string]skills.LockedVariableDeclaration, stored map[string]bool, available bool) []VariableRequirement

UnmetVariables lists required pack declarations absent from stored. available false (locked or unread vault) yields nothing, matching the add-time display: the apply gate then falls through to the loader.

Jump to

Keyboard shortcuts

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