app

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MPL-2.0 Imports: 73 Imported by: 0

Documentation

Overview

Package app implements the FXVCS use cases behind the public SDK. It owns the opened-checkout context (Repo): Git directories resolved through Git, committed and local configuration, the object cache, the per-worktree state database, the shared publication ledger, configured object stores, and the cross-process lock set. sdk.Client methods are thin adapters over this package; nothing here prints, prompts, or exits.

Index

Constants

View Source
const (
	ObjectKindWhole    = pointer.EncodingWhole // the whole file, one object
	ObjectKindChunk    = "chunk/1"             // one content-defined chunk
	ObjectKindManifest = "manifest/1"          // the canonical object manifest
)

Object kinds recorded in the publication ledger's encoding column. They describe what a *stored object* is, which is not the same as the pointer encoding: one cdc-fastcdc/1 pointer is backed by one manifest object and many chunk objects.

View Source
const (
	FindingIndexWorktree = "index-worktree" // state table: hydrated-modified, conflict, missing
	FindingStateDerived  = "state-derived"  // state.db row/journal disagrees with facts, or is unusable
	FindingPublication   = "publication"    // ledger vs cache vs index disagreements
	FindingCache         = "cache"          // cached object disagrees with its pointer
	FindingGitConfig     = "git-config"     // driver config / hook missing or stale
)

Finding kinds (sdk.DoctorFinding.Kind).

View Source
const (
	StageResolving        = "resolving"
	StageTransferring     = "downloading"
	StageWriting          = "writing"
	StageVerifying        = "verifying"
	ProgressPhaseTransfer = "transfer"
	ProgressPhaseWrite    = "write"
	ProgressPhaseVerify   = "verify"
)

prefetchSelection warms the cache for every entry that will need object bytes, and reports which asset each arriving object belongs to so the operation shows movement while it downloads.

Entries whose content is already local are left out, which is what makes a re-run of `hydrate` cost nothing. Entries that will turn out to be skipped for another reason (a modified working file) may have their objects fetched unnecessarily; that costs bandwidth in an uncommon case and never correctness, whereas observing every path twice to find out would cost a re-hash of every large file. Stages of a load. They are named because they behave differently: resolving is index work plus small metadata reads, transferring is bound by the link, and writing is bound by the disk and is serialized per path.

View Source
const (
	// ReuseCached: every object was already in the local object cache.
	ReuseCached = "cached"
	// ReuseShared: identical content to another asset in the same operation,
	// so one transfer served both. This is content addressing paying for
	// itself, and it is worth saying out loud.
	ReuseShared = "shared"
)

Reuse values for PathOutcome and ItemProgress. Empty means the content was transferred during this operation.

View Source
const (
	ProfileGeneric = "generic"
	ProfileFiveM   = "fivem"
)

Profiles.

View Source
const (
	RuleSourceBlock = "fxvcs-block" // a line inside the managed block
	RuleSourceUser  = "user"        // a line of .gitattributes outside the block
	RuleSourceOther = "other"       // effective attribute comes from elsewhere (nested file, info/attributes, global)
	RuleSourceNone  = "none"
)

Rule sources reported by TrackingCheck.

View Source
const (
	UpgradeCheck = "check"
	UpgradePlan  = "plan"
	UpgradeApply = "apply"
)

Upgrade modes.

View Source
const (
	StepCommittedFile = "committed-file"
	StepGitConfig     = "git-config"
	StepHook          = "hook"
	StepLauncher      = "launcher"
	StepLocalState    = "local-state"
)

Upgrade step kinds.

View Source
const AttributesPath = ".gitattributes"

AttributesPath is the root .gitattributes file that carries the managed block. Nested .gitattributes files are honored by Git but never edited by FXVCS.

View Source
const CfgMaxExecDepth = 16

CfgMaxExecDepth bounds nested `exec` chains.

View Source
const DefaultLockTimeout = 10 * time.Second

DefaultLockTimeout is how long an operation waits for a lock another process holds before giving up on that path.

FXVCS deliberately has no daemon, so the CLI, the desktop application and the filter processes Git spawns all take these locks independently, and two of them wanting the same path at the same moment is ordinary rather than exceptional. Every hold is bounded local work — one file's compare-and-swap, one clean — so the wait that absorbs a collision is short, and an operation that fails a path instead of waiting a moment for it makes the operator do by hand what the process could have done by waiting.

Ten seconds is far longer than any legitimate hold and still short enough that a stuck lock is reported while someone is watching.

View Source
const FetchConcurrency = 24

FetchConcurrency bounds simultaneous object downloads.

Downloads are bound by round trips for the same reason uploads are: a chunked asset is many small objects, and a handful at a time leaves the link idle. It matches the publisher's default and the backend's idle-connection pool, so the workers reuse connections rather than renegotiating TLS.

View Source
const MinimumVersionFloor = "0.0.0-0"

MinimumVersionFloor is the minimumFXVCSVersion written by a prerelease (development) binary. A prerelease cannot claim a meaningful floor and SemVer orders every prerelease of 0.0.0 above "0.0.0-0", so this value admits every build. Release binaries write their own version instead.

Variables

View Source
var (
	// ErrConflict: the index blob or the working file changed under an
	// operation, or the working file is in a state automation may not touch
	// (hydrated-modified, conflict). Nothing was written.
	ErrConflict = errors.New("app: checkout conflict")
	// ErrIntegrity: a pointer or object failed verification (malformed
	// pointer, manifest mismatch, digest/size mismatch, wrong storage domain).
	ErrIntegrity = errors.New("app: integrity check failed")
	// ErrObjectUnavailable: an object is neither cached nor available from
	// any configured remote.
	ErrObjectUnavailable = errors.New("app: object not available")
	// ErrObjectNotCached: an object is not in the local cache, and the caller
	// asked for an answer without contacting a remote. It is deliberately
	// distinct from ErrObjectUnavailable: this one means "not here yet", which
	// a download can fix, where the other means the content could not be found
	// anywhere this repository can reach.
	ErrObjectNotCached = errors.New("app: object not cached")
	// ErrNotManaged: a selected path has no filter=fxvcs attribute or is not
	// in the index.
	ErrNotManaged = errors.New("app: path is not managed by fxvcs")
)

Checkout-consistency errors. They are the typed causes behind refused or aborted per-path operations; the SDK maps them to codes.

View Source
var (
	// ErrProfileRequired: the repository profile is not fivem.
	ErrProfileRequired = errors.New("app: operation requires spec.profile fivem")
	// ErrDescriptorMissing: the repository has no accepted component descriptor.
	ErrDescriptorMissing = errors.New("app: no accepted component descriptor (sourceRoot/layout) in .fxvcs/repository.yaml")
	// ErrCatalogInvalid: .fxvcs/resources.yaml does not validate against its schema.
	ErrCatalogInvalid = errors.New("app: resource catalog is invalid")
	// ErrResourceNotFound: `resources set` named a path that is not in the catalog.
	ErrResourceNotFound = errors.New("app: resource path not in catalog")
	// ErrResourceScan: discovery or sandboxed manifest evaluation failed.
	ErrResourceScan = errors.New("app: resource scan failed")
	// ErrCatalogNotReleasable: the catalog failed release-style validation.
	ErrCatalogNotReleasable = errors.New("app: resource catalog is not releasable")
)

Errors.

View Source
var (
	// ErrAlreadyInitialized: .fxvcs/repository.yaml already exists.
	ErrAlreadyInitialized = errors.New("app: repository is already initialized (.fxvcs/repository.yaml exists)")
	// ErrDiscovery wraps a fail-closed FiveM layout detection; the cause is a
	// *discovery.Error carrying candidates.
	ErrDiscovery = errors.New("app: fivem layout could not be determined")
)

Lifecycle errors. They are sentinels so the SDK can map them to stable codes.

View Source
var (
	// ErrNotTracked: a selected path matches no managed rule.
	ErrNotTracked = errors.New("app: path is not tracked by an FXVCS rule (run: fxvcs track <path> or fxvcs track --glob <pattern>)")
	// ErrDirty: the working file differs from the index; migrate refuses.
	ErrDirty = errors.New("app: working file differs from the index; commit or stash it before migrating")
	// ErrSetupRequired: the filter driver is not configured in this clone.
	ErrSetupRequired = errors.New("app: filter driver is not configured in this clone (run: fxvcs setup)")
	// ErrStagedMismatch: git add did not stage the expected pointer.
	ErrStagedMismatch = errors.New("app: staged blob is not the expected pointer; check the filter installation")
)

Migration errors.

View Source
var (
	ErrNotRepository   = repository.ErrNotRepository
	ErrNoSuchRemote    = errors.New("app: no such storage remote")
	ErrRemoteUnbound   = errors.New("app: remote has no local binding on this machine")
	ErrUnsupportedType = errors.New("app: unsupported storage remote type")
	ErrInvalidArgument = errors.New("app: invalid argument")
	ErrNotGitWorktree  = errors.New("app: repository root is not a Git working tree")
)

Errors.

View Source
var ErrCfg = errors.New("app: server.cfg import")

ErrCfg classifies every server.cfg import failure.

View Source
var ErrLauncherVersionConflict = errors.New("app: launcher has the same version but different content")

ErrLauncherVersionConflict means two different launcher binaries report the same semantic version. There is no safe newest-wins ordering; a trusted caller must explicitly request repair to replace the installed bytes.

View Source
var ErrNoCredentials = errors.New("app: no credentials for this storage remote")

ErrNoCredentials: an S3 remote has no usable identity on this machine.

View Source
var ErrRuleCovered = errors.New("app: path is covered by another tracking rule")

ErrRuleCovered: untrack of a literal path that has no exact rule but is still matched by another rule.

View Source
var ErrStack = errors.New("app: stack")

ErrStack marks a coordination-composition failure.

View Source
var ErrTestBinaryLauncher = errors.New("app: refusing to install a Go test binary as the driver launcher outside a temp directory")

ErrTestBinaryLauncher refuses to install a Go test binary as the launcher anywhere outside the temp directory. Git would otherwise run the test binary as the filter/diff/merge driver of a real repository — and a binary whose only behaviour is to run a test suite would run it recursively.

This is not "tests cannot use the SDK": a test binary may be its own launcher inside a temp directory, provided it delegates driver invocations back into the CLI. See fxvcs.dev/fxvcs/sdk/driver.

View Source
var ErrUpgradeConflict = errors.New("app: managed content differs from the plan; re-run fxvcs upgrade and review the working tree")

ErrUpgradeConflict: managed content changed between plan and apply, or a user edit sits inside FXVCS-owned content. Nothing further is written.

Functions

func EncodeResourceCatalog

func EncodeResourceCatalog(cat *domain.ResourceCatalog) ([]byte, error)

EncodeResourceCatalog renders the catalog in its canonical committed form: yaml.v3 over the domain struct (field order fixed by the struct, two-space indent, empty lists as `[]`, no document markers). Two catalogs that are equal as values encode to identical bytes.

func LiteralRule

func LiteralRule(root, rel string) (string, error)

LiteralRule converts a repository-relative path into the exact .gitattributes pattern that matches it and nothing else: the path is pathsafe-normalized, anchored with a leading slash (an unanchored pattern without a slash would match the basename anywhere), glob metacharacters (\ * ? [ ]) are backslash-escaped so FiveM bracket directories match literally, an existing directory gets a trailing "/**" (attributes never apply to a directory recursively), and when the result contains whitespace it is C-escaped because AttributesBlock wraps such patterns in double quotes that Git unquotes C-style.

func LoadLocalConfig

func LoadLocalConfig(path string) (*domain.LocalConfig, error)

LoadLocalConfig reads $GIT_COMMON_DIR/fxvcs/config.yaml; a missing file is an empty config.

func NewStack

func NewStack(stackID, name, profile, minimumVersion string) *domain.Stack

NewStack builds an empty stack document.

func SaveLocalConfig

func SaveLocalConfig(path string, lc *domain.LocalConfig) error

SaveLocalConfig writes the local config atomically.

func SkipWarnings

func SkipWarnings(skipped []discovery.Skipped) []string

SkipWarnings renders skipped manifests as operator-facing warning lines.

Types

type Action

type Action string

Action names something the engine can do to an asset.

const (
	// ActionLoad materializes the real bytes at the working path.
	ActionLoad Action = "load"
	// ActionUnload replaces the working file with its placeholder.
	ActionUnload Action = "unload"
	// ActionPublish uploads the asset's objects to every required remote.
	ActionPublish Action = "publish"
	// ActionStage records the working file in the Git index.
	//
	// Unlike the others there is no fxvcs operation behind it: the operation is
	// `git add`, and whether Git *can* stage a path is Git's business. What an
	// interface cannot see, and what this answers, is what the clean filter
	// would do to those bytes on the way in — which is the difference between
	// staging a texture and staging a placeholder.
	ActionStage Action = "stage"
	// ActionDiscard throws away working changes, restoring the working file
	// from the index pointer.
	ActionDiscard Action = "discard"
)

type ApplyDependencies

type ApplyDependencies struct {
	Supervisor               supervisor.Adapter
	PlayerCountObserver      supervisor.PlayerCountObserver
	RCONTransport            rcon.Transport
	Readiness                readiness.Runner
	Verifiers                verifier.Registry
	Now                      func() time.Time
	Sleep                    func(context.Context, time.Duration) error
	EvaluateActivationWindow func(context.Context, string, time.Time) (bool, error)
	Failpoint                func(string) error
	Progress                 func(string)
	LockTimeout              time.Duration
}

ApplyDependencies are the typed host boundaries used by reconciliation. The coordinator owns ordering, durability and state transitions; process and readiness I/O remain injectable so the exact same engine is crash-tested.

type ApplyResult

type ApplyResult struct {
	Plan       reconcile.PlanResult
	Deployment domain.Deployment
	Applied    bool
}

type AssemblyFile

type AssemblyFile struct {
	Path      string `json:"path"`
	Digest    string `json:"digest"`
	Bytes     int64  `json:"bytes"`
	Mode      string `json:"mode"`
	Placement string `json:"placement"` // hardlink | executable-copy | mutable-copy
}

type AssemblyHookOutput

type AssemblyHookOutput struct {
	ID             string
	Destination    string
	Mode           string
	Rendered       []byte
	ContainsSecret bool
}

type AssemblyMetadata

type AssemblyMetadata struct {
	FormatVersion   int                      `json:"formatVersion"`
	RealizationID   string                   `json:"realizationID"`
	Inputs          domain.RealizationInputs `json:"inputs"`
	Files           []AssemblyFile           `json:"files"`
	PersistentPaths []AssemblyPersistentPath `json:"persistentPaths,omitempty"`
	MutableBytes    int64                    `json:"mutableBytes"`
}

type AssemblyOptions

type AssemblyOptions struct {
	Hooks                    []AssemblyHookOutput
	HookDigests              map[string]string
	SecretVersions           map[string]string
	RuntimeEvidence          *runtimecheck.Evidence
	ExternalVerifierEvidence map[string]string
	ResourceStateToken       []byte
}

type AssemblyPersistentPath

type AssemblyPersistentPath struct {
	RepositoryID string `json:"repositoryID"`
	ResourcePath string `json:"resourcePath"`
	Declared     string `json:"declared"`
	Path         string `json:"path"` // realization-relative symlink path
	Kind         string `json:"kind"`
}

type AssemblyResult

type AssemblyResult struct {
	StagingPath         string
	Metadata            AssemblyMetadata
	MetadataPath        string
	VerificationDigests map[string]string // ephemeral byte digests, including secret-bearing generated files
}

type Availability

type Availability struct {
	Action Action
	// Available is whether the operation would act. False covers both refusal
	// and "nothing to do".
	Available bool
	// Done is true when the asset is already in the requested state, which is
	// a different thing from being refused: an interface should show it as
	// satisfied, not as an error.
	Done bool
	// Reason explains a false Available, in the same words the operation uses.
	Reason string
	// Err is the typed cause when the action is refused rather than done.
	Err error
}

Availability is the answer for one action on one asset.

type CacheCorruption

type CacheCorruption struct {
	Domain string
	Digest string
	Bytes  int64
	Pinned bool
	Reason string
}

CacheCorruption is one object that failed verification.

type CacheEviction

type CacheEviction struct {
	Domain string
	Digest string
	Bytes  int64
	Err    error
}

CacheEviction is one planned or executed cache removal.

type CacheSummary

type CacheSummary struct {
	Dir            string
	TotalBytes     int64
	PinnedBytes    int64
	EvictableBytes int64
	Objects        int
	Pinned         int
	// LimitBytes is the automatic-trim budget this clone configured (0 = none).
	LimitBytes int64
}

CacheSummary describes cache usage for this repository's storage domain.

type CacheVerifyOptions

type CacheVerifyOptions struct {
	// AllDomains verifies every storage domain in the cache, not only this
	// repository's.
	AllDomains bool
	// Repair removes corrupt objects so the next operation refetches them.
	// A corrupt object that is pinned (pending publication) is never removed:
	// see CacheVerifyReport.Kept.
	Repair bool
}

CacheVerifyOptions configures CacheVerify.

type CacheVerifyProgress

type CacheVerifyProgress struct {
	Done, Total    int
	Domain, Digest string
	Bytes          int64
	Started        bool
	Err            error
}

CacheVerifyProgress describes one cache object before and after its bytes are hashed. An empty Digest is the operation-wide plan.

type CacheVerifyReport

type CacheVerifyReport struct {
	// Checked and Bytes count what was read.
	Checked int
	Bytes   int64
	// Corrupt lists objects whose bytes no longer hash to their name.
	Corrupt []CacheCorruption
	// Removed counts corrupt objects dropped by Repair.
	Removed int
	// Kept counts corrupt objects that were left in place because they are
	// pinned: their bytes are the only copy of something not yet published,
	// so deleting them would destroy data rather than recover it.
	Kept []CacheCorruption
}

CacheVerifyReport is the result of re-reading cached objects.

type CatalogInvalidError

type CatalogInvalidError struct {
	File   string
	Issues schema.Issues
}

CatalogInvalidError carries schema issues of .fxvcs/resources.yaml.

func (*CatalogInvalidError) Error

func (e *CatalogInvalidError) Error() string

func (*CatalogInvalidError) Is

func (e *CatalogInvalidError) Is(target error) bool

func (*CatalogInvalidError) Unwrap

func (e *CatalogInvalidError) Unwrap() error

type CfgError

type CfgError struct {
	File   string
	Line   int
	Reason string // "unreadable" | "absolute-path" | "escapes-root" | "cycle" | "too-deep"
	Detail string
	Err    error
}

CfgError is a typed server.cfg import failure. File is the offending cfg path relative to the cfg root ("" for the root file itself when it cannot be read); Line is 1-based (0 when not line-specific).

func (*CfgError) Error

func (e *CfgError) Error() string

func (*CfgError) Is

func (e *CfgError) Is(target error) bool

func (*CfgError) Unwrap

func (e *CfgError) Unwrap() error

type CfgImport

type CfgImport struct {
	// Root is the absolute directory of the top-level cfg; every File is
	// relative to it.
	Root string `json:"root"`
	// Resources are the resource names started by ensure/start, sorted and
	// de-duplicated.
	Resources []string `json:"resources"`
	// Files lists every cfg file that was parsed, root-relative with '/'
	// separators, in first-visit order.
	Files []string `json:"files"`
	// Warnings describe skipped constructs (resource-relative exec, stop
	// lines, invalid names) as "<file>:<line>: <message>".
	Warnings []string `json:"warnings"`
}

CfgImport is the result of parsing a server configuration tree.

func ParseServerCfg

func ParseServerCfg(path string) (CfgImport, error)

ParseServerCfg parses path and every cfg it execs (see the package notes above). The cfg root is the directory containing path.

func (CfgImport) Has

func (c CfgImport) Has(name string) bool

Has reports whether name was started by the imported configuration.

type CloneInput

type CloneInput struct {
	URL string
	// Directory is the target directory (absolute or relative to Cwd); empty
	// derives it from the URL like git does.
	Directory string
	// Cwd resolves a relative Directory ("" = process cwd).
	Cwd string
	// Blobless passes --filter=blob:none so pre-migration binary history is
	// not downloaded.
	Blobless bool
	// LauncherPath is passed to Setup.
	LauncherPath string
}

CloneInput configures Clone.

type CloneResult

type CloneResult struct {
	Root  string
	Setup SetupResult
}

CloneResult reports the new checkout.

func Clone

func Clone(ctx context.Context, in CloneInput, opts Options) (CloneResult, error)

Clone runs `git clone` (without any fxvcs driver configured, so Git checks out committed pointer bytes exactly as stored: an unhydrated checkout is always safe), then opens the checkout and runs Setup. Hydration is a separate, explicit step; the caller performs it when requested.

type ComponentProposal

type ComponentProposal struct {
	RepositoryID   string                     `json:"repositoryID"`
	Name           string                     `json:"name"`
	Remote         string                     `json:"remote"`
	Ref            string                     `json:"ref,omitempty"`
	Commit         string                     `json:"commit"`
	Profile        string                     `json:"profile"`
	Descriptor     domain.ComponentDescriptor `json:"descriptor"`
	DescriptorFrom string                     `json:"descriptorFrom"`
	Mount          string                     `json:"mount"`
	Alias          string                     `json:"alias,omitempty"`
	Required       bool                       `json:"required"`
	// Resources is the number of resources in the pinned catalog.
	Resources int `json:"resources"`
	// Detected is the layout discovery found in the pinned tree; it is shown
	// next to the component's own declaration so a disagreement is visible.
	Detected *domain.ComponentDescriptor `json:"detected,omitempty"`
}

ComponentProposal is what add or rescan detected.

type ComponentStatus

type ComponentStatus struct {
	RepositoryID string `json:"repositoryID"`
	Name         string `json:"name,omitempty"`
	Remote       string `json:"remote"`
	Ref          string `json:"ref,omitempty"`
	Mount        string `json:"mount"`
	Required     bool   `json:"required"`
	Fetched      bool   `json:"fetched"`
	Commit       string `json:"commit,omitempty"`
	Resources    int    `json:"resources,omitempty"`
	Error        string `json:"error,omitempty"`
	// ReleasedCommit is what the newest release pins for this component, when
	// there is one; a difference is exactly the drift an operator cares about.
	ReleasedCommit string `json:"releasedCommit,omitempty"`
	Drifted        bool   `json:"drifted,omitempty"`
}

ComponentStatus is one row of stack status.

type ComponentSync

type ComponentSync struct {
	RepositoryID string `json:"repositoryID"`
	Remote       string `json:"remote"`
	Ref          string `json:"ref,omitempty"`
	Commit       string `json:"commit,omitempty"`
	// Previous is the commit the mirror had before the fetch.
	Previous string `json:"previous,omitempty"`
	Updated  bool   `json:"updated"`
	Error    string `json:"error,omitempty"`
}

ComponentSync is one component's fetch outcome.

type Content

type Content struct {
	Pointer  pointer.Pointer
	Manifest domain.ObjectManifest
	// Objects lists the manifest object (chunked encodings only, because a
	// whole/1 manifest is derived from the pointer and never stored) followed
	// by the chunks in file order.
	Objects []ContentObject
}

Content is the resolved storage plan for one pointer: the manifest plus every object that must exist before the file can be materialized.

func (Content) Chunked

func (c Content) Chunked() bool

Chunked reports whether the pointer is backed by more than the file itself.

func (Content) Digests

func (c Content) Digests() []string

Digests returns every object digest the pointer depends on.

func (Content) StoredBytes

func (c Content) StoredBytes() int64

StoredBytes is the total size of the objects behind the pointer.

type ContentObject

type ContentObject struct {
	Digest string
	Size   int64
	Kind   string
}

ContentObject is one stored object behind a pointer.

type Coord

type Coord struct {
	*gitops.Repo
	// contains filtered or unexported fields
}

Coord is an opened coordination repository: the stack, its releases, environments and targets, and the component mirrors underneath it.

It deliberately is not a *Repo. A coordination repository holds no tracked assets, no hydration state, and no publication ledger; giving it the same type would invite operations that make no sense there.

func OpenCoord

func OpenCoord(ctx context.Context, start string, opts Options) (*Coord, error)

OpenCoord locates and opens the coordination repository containing start.

func (*Coord) ApplyTarget

func (c *Coord) ApplyTarget(ctx context.Context, targetName string, config domain.AgentConfig, binding domain.AgentTargetBinding, deps ApplyDependencies) (ApplyResult, error)

ApplyTarget executes one complete target attempt under the cross-process target lock. It never reports success before immutable publication, journaled activation, a proved new process generation, and readiness soak.

func (*Coord) AssembleReleaseStaging

func (c *Coord) AssembleReleaseStaging(ctx context.Context, rel domain.Release, inputs domain.RealizationInputs, realizationID, deployRoot string) (AssemblyResult, error)

AssembleReleaseStaging builds an unselectable, same-filesystem realization staging tree. Publication and current activation are separate journaled operations; a successful return does not make this tree live.

func (*Coord) AssembleReleaseStagingWithOptions

func (c *Coord) AssembleReleaseStagingWithOptions(ctx context.Context, rel domain.Release, inputs domain.RealizationInputs, realizationID, deployRoot string, options AssemblyOptions) (AssemblyResult, error)

AssembleReleaseStagingWithOptions adds already-resolved deterministic hook outputs to an unselectable realization. Secret-bearing byte digests remain ephemeral and are never persisted in realization metadata.

func (*Coord) EnvironmentList

func (c *Coord) EnvironmentList(ctx context.Context) ([]EnvironmentResult, error)

EnvironmentList lists every environment.

func (*Coord) EnvironmentSet

func (c *Coord) EnvironmentSet(ctx context.Context, in EnvironmentSetInput) (*EnvironmentResult, error)

EnvironmentSet creates or updates an environment. Every change that alters content bumps the revision, because a realization's identity includes the environment revision: an unchanged number would let a target look reconciled against configuration that moved underneath it.

func (*Coord) EnvironmentShow

func (c *Coord) EnvironmentShow(ctx context.Context, name string) (*EnvironmentResult, error)

EnvironmentShow reads one environment. It never shows a secret value because an environment never holds one; it holds the scope those values are looked up in.

func (*Coord) MaterializeReleaseContent

func (c *Coord) MaterializeReleaseContent(ctx context.Context, rel domain.Release, deployRoot string) ([]MaterializedContent, error)

MaterializeReleaseContent reconstructs every pointer-backed file required by a pinned Release into the target's verified materialized store. It does not assemble or activate a realization.

func (*Coord) Now

func (c *Coord) Now() func() time.Time

Now returns the clock.

func (*Coord) ObjectChecker

func (c *Coord) ObjectChecker(ctx context.Context) (release.ObjectChecker, error)

ObjectChecker returns the release object checker for this coordination repository, or nil when checking is disabled.

func (*Coord) ReleaseCreate

func (c *Coord) ReleaseCreate(ctx context.Context, in ReleaseCreateInput) (*ReleaseCreateResult, error)

ReleaseCreate resolves the composition, builds the immutable record, and writes it. It never commits: the release exists once a human commits the file, which keeps the Git provider's review, history, and protection rules in the loop.

func (*Coord) ReleaseExport

func (c *Coord) ReleaseExport(ctx context.Context, name string) (*ReleaseExportResult, error)

ReleaseExport returns one release as a portable document.

func (*Coord) ReleaseImport

func (c *Coord) ReleaseImport(ctx context.Context, data []byte) (*release.ImportResult, error)

ReleaseImport validates and stores a portable release document.

func (*Coord) ReleaseInspect

func (c *Coord) ReleaseInspect(ctx context.Context, name, compareTo string) (*ReleaseInspectResult, error)

ReleaseInspect explains a release from its record alone.

func (*Coord) ReleaseList

func (c *Coord) ReleaseList(ctx context.Context) ([]ReleaseListRow, error)

ReleaseList lists every release with the targets that select it.

func (*Coord) ReleaseNotes

func (c *Coord) ReleaseNotes(ctx context.Context, name, since string) (*ReleaseNotesResult, error)

ReleaseNotes drafts Markdown notes from the change set between two releases. The draft is never written into the release record: prose is a separate, separately versioned artifact, so editing it cannot change release identity.

func (*Coord) ResolveAssemblyHooks

func (c *Coord) ResolveAssemblyHooks(ctx context.Context, target domain.Target, environment domain.Environment, rel domain.Release, binding domain.AgentTargetBinding, secretResolver templatehook.SecretResolver) (AssemblyOptions, error)

ResolveAssemblyHooks validates pinned template identity and host allowlists, resolves typed inputs, and renders every pre-activation template output in deterministic phase/request order. It performs no deployment-root writes.

func (*Coord) ResolveTargetPlan

func (c *Coord) ResolveTargetPlan(ctx context.Context, targetName string, config domain.AgentConfig, binding domain.AgentTargetBinding) (reconcile.PlanResult, error)

ResolveTargetPlan loads and verifies the immutable desired-state inputs for one target before handing them to the pure Stage 4 planner. It performs no activation, runtime control, or agent database mutation.

func (*Coord) ResolveTargetPlanWithObservations

func (c *Coord) ResolveTargetPlanWithObservations(ctx context.Context, targetName string, config domain.AgentConfig, binding domain.AgentTargetBinding, observations TargetPlanObservations) (reconcile.PlanResult, error)

func (*Coord) RuntimeResourcesSync

func (c *Coord) RuntimeResourcesSync(ctx context.Context, in RuntimeResourcesSyncInput) (*RuntimeResourcesSyncResult, error)

RuntimeResourcesSync proposes coordination-owned runtime/external entries from an existing server.cfg. Every proposal is `pending` with an `external:` ID: the source kind of a resource that is merely mentioned in a cfg is genuinely unknown, and guessing it from a familiar name is how a server ends up depending on a resource nobody owns. It never commits.

func (*Coord) StackAdd

func (c *Coord) StackAdd(ctx context.Context, in StackAddInput) (*StackAddResult, error)

StackAdd fetches a component repository, reads its committed identity and layout, proposes a mount, and records it in fxvcs.yaml. It never commits.

func (*Coord) StackRescan

func (c *Coord) StackRescan(ctx context.Context, only []string, accept bool) (*StackRescanResult, error)

StackRescan re-detects each component's layout at its current ref and reports disagreement with what the stack recorded. It changes nothing unless accept is set — a mount is a realization-shape decision, and silently moving one would silently move files on every target.

func (*Coord) StackStatus

func (c *Coord) StackStatus(ctx context.Context) (*StackStatusResult, error)

StackStatus reads local state only; it never touches the network.

func (*Coord) StackSync

func (c *Coord) StackSync(ctx context.Context, only []string, progress func(ComponentSync)) (*StackSyncResult, error)

StackSync fetches every component repository (or the named ones) into its mirror. It is the only stack operation that uses the network.

func (*Coord) StackValidate

func (c *Coord) StackValidate(ctx context.Context) (*StackValidateResult, error)

StackValidate resolves the whole composition from the currently fetched component refs and reports the plan a release would snapshot. It writes nothing and uses no network.

func (*Coord) StorageBind

func (c *Coord) StorageBind(in StorageAddInput) (RemoteView, error)

StorageBind records how this machine reaches one storage remote from the coordination repository.

A coordination repository owns no storage of its own — the remote descriptors belong to the component repositories. But release creation has to verify that every asset a component pins is already in storage, and for a filesystem remote that means knowing the directory on *this* machine. `fxvcs storage add` therefore falls back to this when it is run outside a component checkout: same command, same flags, purely local effect.

func (*Coord) TargetList

func (c *Coord) TargetList(ctx context.Context) ([]TargetResult, error)

TargetList lists every target.

func (*Coord) TargetSet

func (c *Coord) TargetSet(ctx context.Context, in TargetSetInput) (*TargetResult, error)

TargetSet creates or updates a target. The release must already exist as a record here: pointing a target at a name nobody has committed is how a fleet ends up waiting for a release that will never arrive.

func (*Coord) TargetShow

func (c *Coord) TargetShow(ctx context.Context, name string) (*TargetResult, error)

TargetShow reads one target's desired state and what the release it selects would start. Locally observed deployment state belongs to the agent (Stage 4) and is deliberately absent here.

type DoctorOptions

type DoctorOptions struct {
	// Launcher is the absolute launcher path the Git configuration must
	// point at ("" = the recorded path, with exact legacy-default migration,
	// else the canonical per-user default).
	Launcher string
}

DoctorOptions configures Doctor and Repair.

type EnvironmentResult

type EnvironmentResult struct {
	Name        string            `json:"name"`
	File        string            `json:"file"`
	Revision    int               `json:"revision"`
	Inputs      map[string]string `json:"inputs"`
	SecretScope string            `json:"secretScope"`
	Created     bool              `json:"created,omitempty"`
	Changed     bool              `json:"changed,omitempty"`
	// UsedBy names targets referencing this environment.
	UsedBy []string `json:"usedBy,omitempty"`
}

EnvironmentResult is one environment record.

type EnvironmentSetInput

type EnvironmentSetInput struct {
	Name string
	// Inputs are non-secret values, "key=value". Setting a key to the empty
	// string removes it.
	Inputs []string
	// SecretScope is the logical secret namespace scope (default: the name).
	SecretScope string
}

EnvironmentSetInput creates or updates one environment.

type Finding

type Finding struct {
	Path       string
	Kind       string
	Message    string
	Repairable bool
}

Finding is one doctor result.

type IndexEntry

type IndexEntry struct {
	Path     string
	BlobOID  string // git object id of the index blob
	Stage    int    // 0 merged; 1..3 unmerged
	Unmerged bool
	// Pointer is set when the blob decodes as a supported pointer.
	Pointer    pointer.Pointer
	HasPointer bool
	// PointerErr records why the blob is not a usable pointer: nil for a
	// historical raw blob (not attributed to any object), otherwise the
	// decode/derivation failure (unsupported version, malformed, manifest
	// mismatch, wrong storage domain).
	PointerErr error
	IsPointer  bool // bytes sniff as a pointer of some version
	BlobSize   int64
}

IndexEntry is one managed path as recorded in the Git index together with its decoded pointer when the blob is one.

type Ingested

type Ingested struct {
	Pointer  pointer.Pointer
	Digest   string // whole-file sha256 (== Pointer.OID)
	Size     int64
	Manifest domain.ObjectManifest
	// Objects lists every stored object the pointer depends on: for whole/1
	// the file itself, for a chunked encoding the manifest and its chunks.
	Objects []ContentObject
	// Existing is true when nothing new had to be written: every object was
	// already cached and recorded.
	Existing bool
}

Ingested describes the objects a single ingestion durably recorded.

type InitInput

type InitInput struct {
	// Path is any directory inside the Git working tree to initialize.
	Path string
	// Name is metadata.name; empty selects the working-tree basename.
	Name string
	// Profile is generic (default) or fivem.
	Profile string
	// StorageDomainID overrides the generated storage domain (rare: a
	// repository that intentionally shares a domain with another).
	StorageDomainID string
	// FiveM descriptor overrides; when all are empty, discovery proposes them.
	SourceRoot   string
	Layout       string
	ResourceName string
	// RemoteName/RemotePath register one committed filesystem remote
	// (requiredForPublication) and bind it locally.
	RemoteName string
	RemotePath string
	// LauncherPath is passed to Setup.
	LauncherPath string
}

InitInput configures Init.

type InitResult

type InitResult struct {
	Root            string
	RepositoryID    string
	StorageDomainID string
	Name            string
	Profile         string
	// Detection is the accepted FiveM descriptor (fivem profile only).
	Detection *discovery.Detection
	// FilesWritten lists repository-relative paths written or edited.
	FilesWritten []string
	Setup        SetupResult
	// Track is the preset tracking result (fivem profile only).
	Track *TrackResult
}

InitResult reports what Init created.

func Init

func Init(ctx context.Context, in InitInput, opts Options) (InitResult, error)

Init creates .fxvcs/repository.yaml in the Git working tree containing in.Path, then runs Setup and (for the fivem profile) tracks the binary presets. It never commits. Validation (Git worktree, no existing configuration, name, profile, FiveM layout, schema) completes before the first write.

type IssueKind

type IssueKind string

IssueKind classifies a verification finding; the SDK maps kinds to codes.

const (
	IssueIntegrity IssueKind = "integrity" // malformed pointer, manifest/domain mismatch, corrupt or mis-sized object
	IssueNotFound  IssueKind = "not-found" // object neither cached nor available where required
	IssueStorage   IssueKind = "storage"   // a remote could not be queried
)

type ItemProgress

type ItemProgress struct {
	Path   string
	Digest string
	Bytes  int64
	Total  int64
	Done   bool
	// Planned and PlannedBytes mark the one event an operation emits when its
	// exact work is known: it is about to process Planned items totalling
	// PlannedBytes. Path is empty on that event. Metadata-dependent operations
	// may report indeterminate resolving progress before this event.
	//
	// It exists so a display can show "12 of 600" and a bar that reaches the
	// end. Without it a long operation can only count what it has already
	// seen, which is precisely the number that is not useful while waiting.
	Planned      int
	PlannedBytes int64
	// Fetched marks a transfer report from background prefetching: object
	// bytes arrived for Path, but the file has not been written yet. It moves
	// the transferred total without claiming the item is done, which is the
	// difference between "downloading" and "written to the working tree".
	Fetched bool
	// Chunks and ChunksDone count the stored objects behind the item and how
	// many have arrived. A whole-blob asset has one; a chunked asset has its
	// manifest plus a chunk per content-defined piece, which is what makes
	// "12 of 47 chunks" meaningful to show.
	Chunks, ChunksDone int
	// Reuse says where an item's content came from when it did not have to be
	// transferred; empty means it was.
	Reuse string
	// Stage, with an empty Path, announces which part of the operation is
	// running. A load is three different kinds of work — reading the index and
	// resolving what each asset is made of, transferring what is missing, then
	// writing files — and they have different bottlenecks and different
	// progress. Index and Count position the stage when it can count itself.
	Stage string
	// Index and Count position a stage that can count itself.
	Index, Count int
	// ReusedItems and ReusedBytes accompany a plan event: how many of the
	// planned assets need no transfer at all, and how much that saves. Content
	// addressing is what makes it possible — one copy of a font vendored into
	// forty resources is one stored object — and an operation that silently
	// skips 40% of its bytes should say so.
	ReusedItems int
	ReusedBytes int64
	// PlanPhase says which kind of work PlannedBytes measures. Consumers must
	// not average a transfer denominator with a write denominator: each phase
	// has its own progress and rate.
	PlanPhase string
	// Phase identifies per-item work. Part fields identify the object/chunk
	// within a transfer so SDK consumers can show item-part progress without
	// reconstructing it from asset totals.
	Phase                                          string
	PartID                                         string
	PartBytes, PartTotal, WireBytes, PartWireBytes int64
	PartIndex, PartCount                           int
}

ItemProgress is one progress event of a per-path operation.

func (ItemProgress) IsPlan

func (p ItemProgress) IsPlan() bool

IsPlan reports the operation-wide plan event.

func (ItemProgress) IsStage

func (p ItemProgress) IsStage() bool

IsStage reports a stage announcement.

type LauncherEnsureInput

type LauncherEnsureInput struct {
	SourcePath         string
	TargetPath         string
	CandidateVersion   format.Version
	LockTimeout        time.Duration
	RepairEqualVersion bool
}

LauncherEnsureInput identifies a trusted candidate and stable destination.

type LauncherEnsureResult

type LauncherEnsureResult struct {
	Path             string
	Outcome          LauncherOutcome
	Changed          bool
	CandidateVersion string
	InstalledVersion string
	CandidateSHA256  string
	InstalledSHA256  string
}

LauncherEnsureResult describes the installed and candidate launchers.

func EnsureLauncher

EnsureLauncher applies newest-wins launcher ownership under a durable, cross-process lock. It never downgrades an installed launcher.

func InspectLauncher

func InspectLauncher(ctx context.Context, in LauncherEnsureInput) (LauncherEnsureResult, error)

InspectLauncher compares a trusted candidate with an installed launcher without writing. The candidate version is supplied by the embedding host; installed versions are always probed from the installed executable itself.

type LauncherOutcome

type LauncherOutcome string

LauncherOutcome is the result of comparing or installing a launcher.

const (
	LauncherAlreadyCurrent  LauncherOutcome = "already-current"
	LauncherInstallRequired LauncherOutcome = "install-required"
	LauncherUpdateRequired  LauncherOutcome = "update-required"
	LauncherInstalled       LauncherOutcome = "installed"
	LauncherUpdated         LauncherOutcome = "updated"
	LauncherNewerPresent    LauncherOutcome = "newer-present"
	LauncherVersionConflict LauncherOutcome = "equal-version-conflict"
)

type MaterializedContent

type MaterializedContent struct {
	Digest  string
	Bytes   int64
	Existed bool
	Remote  string
}

type MigrateInput

type MigrateInput struct {
	Paths    []string
	Glob     bool
	Progress ProgressFunc
}

MigrateInput selects index entries to convert.

type MigrateOutcome

type MigrateOutcome struct {
	Path    string
	Digest  string
	Bytes   int64
	Skipped bool
	Reason  string
}

MigrateOutcome is one path's result.

type ObjectInfo

type ObjectInfo struct {
	Digest string
	Size   int64
	// Cached is true when every object behind the pointer is present locally
	// at the size the manifest records.
	//
	// Present, not proven: it is the condition under which a read can proceed
	// without the network, not a guarantee that the read will succeed. The
	// bytes are verified as they stream — a damaged object fails the read
	// rather than being handed over — so establishing this cheaply is right,
	// and a caller must still handle a read failing.
	Cached bool
	// Objects counts the stored objects the content is made of: one for a
	// whole/1 asset, a manifest plus a chunk per piece for a chunked one.
	// Zero when the manifest itself is not cached and the count is unknown.
	Objects int
	// Encoding is the pointer encoding (whole/1, cdc-fastcdc/1).
	Encoding string
}

ObjectInfo is what is known locally about the content behind a pointer.

type ObjectState

type ObjectState struct {
	Digest    string
	Bytes     int64
	Pending   bool
	Remotes   map[string]bool
	Referrers []string
}

ObjectState is one ledger row projected for callers.

type Options

type Options struct {
	Installed format.Version
	Operation string // recorded in lock owner metadata
	// GitExecutable overrides the git binary.
	GitExecutable string
	// CacheDir overrides the host object cache root.
	CacheDir string
	// ConfigDir overrides the user configuration directory that holds the
	// object-store credential file (tests, encrypted volumes).
	ConfigDir string
	// LauncherSourcePath is the trusted headless fxvcs CLI/Engine executable
	// that may be installed for Git. Empty uses os.Executable. Embedding hosts
	// such as fxvcs Desktop must set this to their bundled helper, never the
	// Desktop application executable.
	LauncherSourcePath string
	// LockTimeout bounds waits for busy locks (0 = try once). Entry points
	// that serve an operator — the SDK client and the Git filter — pass
	// DefaultLockTimeout; zero stays fail-fast for callers that mean it.
	LockTimeout time.Duration
	// Now overrides the clock (tests).
	Now func() time.Time
	// Diagnostic marks an operation that reports on the repository rather
	// than acting on it (verify, doctor). Such an operation must not repair
	// what it finds: a check that silently fixes a damaged object and then
	// reports the repository healthy has destroyed the evidence and told the
	// operator nothing happened.
	Diagnostic bool
}

Options configures Open.

type PathOutcome

type PathOutcome struct {
	Path    string
	Digest  string
	Bytes   int64
	Skipped bool
	Reason  string
	// Reuse says the content did not have to be transferred: ReuseCached when
	// the objects were already local, ReuseShared when another asset in the
	// same operation has identical content. Empty means it was transferred.
	Reuse string
	// Err is the typed cause when the item failed (nil for plain refusals
	// such as "already hydrated").
	Err error
}

PathOutcome reports one path's result inside a multi-path operation.

type PathStatus

type PathStatus struct {
	Path        string
	State       state.Condition
	IndexDigest string // pointer OID from the index ("" when the blob is not a pointer)
	Size        int64  // pointer size (the asset's size as recorded in the index) when known
	// WorkingSize is what the working file occupies on disk right now: the
	// asset's real size when it is hydrated, a couple of hundred bytes of
	// placeholder when it is not, zero when the file is absent. It costs
	// nothing — the stat that derives the state already carries it.
	WorkingSize int64
	// SizeDelta is WorkingSize - Size: how much the asset grew or shrank
	// locally. It is nil when the two are not comparable, which is every state
	// in which the working file is a placeholder — subtracting an asset's size
	// from its pointer's would report a 40 MB deletion for a file nobody
	// touched. Non-nil and zero is a real answer: a change that kept the size.
	SizeDelta *int64
	Cached    bool   // object bytes present in the local cache
	Published bool   // recorded on every requiredForPublication remote (ledger)
	Pending   bool   // ingested locally, not yet published everywhere required
	Detail    string // human explanation for conflict/missing rows
	// Actions is what the engine would do to this asset right now, and why
	// not when it would refuse. It is the same decision the operations make;
	// see actions.go.
	Actions []Availability
}

PathStatus is the derived checkout state of one managed path.

type PlannedResource

type PlannedResource struct {
	Name             string `json:"name"`
	Source           string `json:"source"`
	RepositoryName   string `json:"repositoryName,omitempty"`
	Path             string `json:"path,omitempty"`
	ResourceID       string `json:"resourceID,omitempty"`
	Activation       string `json:"activation"`
	ActivationSource string `json:"activationSource"`
	EnsureOrder      int    `json:"ensureOrder"`
	// Mount is where the resource lands in the realization.
	Mount string `json:"mount,omitempty"`
}

PlannedResource is one row of the resolved activation plan.

type ProgressFunc

type ProgressFunc func(ItemProgress)

ProgressFunc receives ItemProgress events (may be nil).

Delivery is serialized: an operation that runs work concurrently still calls this one event at a time, so a consumer needs no synchronization of its own. Callers that fan out must hold their own lock across the call.

type PublicationRemoteUsage

type PublicationRemoteUsage struct {
	Name    string
	Objects int
	Bytes   int64
}

PublicationRemoteUsage is the repository ledger's recorded unique-object footprint for one configured storage backend.

type PublicationSummary

type PublicationSummary struct {
	Objects        int
	Bytes          int64
	PendingObjects int
	PendingBytes   int64
	Remotes        []PublicationRemoteUsage
}

PublicationSummary is the repository ledger's unique-object footprint and the part of it not yet present on every required remote.

type PublishEvent

type PublishEvent struct {
	Kind        PublishEventKind
	Item        PublishItem // for Started/Progress/Finished/Failed
	Transferred int64       // bytes transferred so far for Item (Progress) or total (Finished)
	Err         error       // Failed only
	Plan        []PublishItem
	TotalBytes  int64 // Plan/Done: sum of planned bytes; Done: bytes uploaded
	Skipped     int   // Done: uploads skipped because the remote already had the object
}

PublishEvent is the streamed progress record. A consumer receives, in order: one Plan event (Items lists every upload with sizes; nothing has started), then per item Started / Progress* / Finished-or-Failed, possibly interleaved across up to Concurrency items, then one Done event.

type PublishEventKind

type PublishEventKind string

PublishEventKind enumerates PublishEvent kinds.

const (
	PublishPlan       PublishEventKind = "plan"
	PublishStarted    PublishEventKind = "started"
	PublishProgressed PublishEventKind = "progress"
	PublishFinished   PublishEventKind = "finished"
	PublishFailed     PublishEventKind = "failed"
	PublishDone       PublishEventKind = "done"
)

type PublishItem

type PublishItem struct {
	Digest string
	Remote string
	Bytes  int64    // object size (0 when unknown until opened)
	Paths  []string // repository paths referring to the object, for display
	// contains filtered or unexported fields
}

PublishItem is one planned upload (digest → remote) with the metadata a UI needs to render it before, during, and after transfer.

type PublishOptions

type PublishOptions struct {
	// Remotes to publish to; empty = every requiredForPublication remote.
	Remotes []string
	// Selection restricts publication to the objects behind the given managed
	// paths, which is what makes a per-asset "upload" control possible: the
	// publish action is reported per asset, so it has to be actionable per
	// asset.
	//
	// Nil means the whole repository, and that is not the same as selecting
	// every path. An object can be pending with no index entry referring to it
	// any more — a path whose content changed again before it was uploaded, or
	// one that has since been deleted — and a repository-wide publish must
	// still upload it, because a Git ref that reaches it is refused until it
	// is there.
	Selection *Selection
	// Concurrency bounds simultaneous uploads (default 4).
	Concurrency int
	// Events receives the streamed plan/progress; may be nil.
	Events func(PublishEvent)
	// ProgressStep is the byte interval between Progress events per item
	// (default 4 MiB).
	ProgressStep int64
}

PublishOptions tunes ObjectsPublish.

type PublishOutcome

type PublishOutcome struct {
	Digest string
	Remote string
	Bytes  int64
	Err    error
	// Paths are the repository paths referring to the object, for display.
	Paths []string
}

PublishOutcome reports one digest×remote upload.

type PublishProgress

type PublishProgress func(digest, remote string, bytes int64, done bool, err error)

PublishProgress receives per-object events. Deprecated shim over PublishEvent kept for callers that only need start/finish; new callers use PublishOptions.Events.

type PublishedAssembly

type PublishedAssembly struct {
	Path    string
	Existed bool
}

func PublishReleaseStaging

func PublishReleaseStaging(result AssemblyResult, deployRoot string) (PublishedAssembly, error)

PublishReleaseStaging atomically moves a complete staging tree into its immutable realization name without replacing any existing directory. An existing realization is accepted only when its canonical metadata is byte identical to the expected assembly.

type ReleaseCreateInput

type ReleaseCreateInput struct {
	Name string
	// Pins are "<repositoryID>=<ref>" overrides of the stack ref.
	Pins []string
	// Enable and Disable are release-only activation overrides.
	Enable, Disable []string
	VariantOf       string
	CreatedBy       string
	// TagComponents creates durable namespaced tags in every component remote
	// before the release is written.
	TagComponents bool
	// SkipObjectCheck skips storage verification entirely.
	SkipObjectCheck bool
	// AllowUnverifiedObjects proceeds when a required remote cannot be reached.
	AllowUnverifiedObjects bool
}

ReleaseCreateInput describes the release to build.

type ReleaseCreateResult

type ReleaseCreateResult struct {
	Name       string                    `json:"name"`
	File       string                    `json:"file"`
	Written    bool                      `json:"written"`
	Digest     string                    `json:"digest"`
	SourceSet  string                    `json:"sourceSetDigest"`
	Components []release.ComponentReport `json:"components"`
	Resources  []PlannedResource         `json:"resources"`
	Enabled    int                       `json:"enabled"`
	Disabled   int                       `json:"disabled"`
	Tags       []release.ComponentTag    `json:"tags,omitempty"`
	Warnings   []string                  `json:"warnings,omitempty"`
	Problems   []stack.Problem           `json:"problems,omitempty"`
	Release    *domain.Release           `json:"release,omitempty"`
	// Change is the diff against the previous release, when there is one.
	Change *release.ChangeSet `json:"change,omitempty"`
}

ReleaseCreateResult is the built release and its review material.

type ReleaseExportResult

type ReleaseExportResult struct {
	Name   string `json:"name"`
	Digest string `json:"digest"`
	// Document is the portable YAML.
	Document []byte `json:"-"`
	Bytes    int    `json:"bytes"`
	File     string `json:"file,omitempty"`
}

ReleaseExportResult is a portable release document.

type ReleaseInspectResult

type ReleaseInspectResult struct {
	Name            string                    `json:"name"`
	File            string                    `json:"file"`
	CreatedAt       string                    `json:"createdAt"`
	CreatedBy       string                    `json:"createdBy,omitempty"`
	StackID         string                    `json:"stackID"`
	Digest          string                    `json:"digest"`
	SourceSetDigest string                    `json:"sourceSetDigest"`
	VariantOf       string                    `json:"variantOf,omitempty"`
	MinimumVersion  string                    `json:"minimumFXVCSVersion,omitempty"`
	Components      []domain.ReleaseComponent `json:"components"`
	Resources       []PlannedResource         `json:"resources"`
	Enabled         int                       `json:"enabled"`
	Disabled        int                       `json:"disabled"`
	// SameSourceAs lists other releases with an identical sourceSetDigest.
	SameSourceAs []string `json:"sameSourceAs,omitempty"`
	// Change is the diff against a requested comparison release.
	Change *release.ChangeSet `json:"change,omitempty"`
}

ReleaseInspectResult explains one release.

type ReleaseListRow

type ReleaseListRow struct {
	Name            string `json:"name"`
	CreatedAt       string `json:"createdAt"`
	CreatedBy       string `json:"createdBy,omitempty"`
	Components      int    `json:"components"`
	Enabled         int    `json:"enabled"`
	SourceSetDigest string `json:"sourceSetDigest"`
	VariantOf       string `json:"variantOf,omitempty"`
	// UsedBy names targets whose desired state is this release.
	UsedBy []string `json:"usedBy,omitempty"`
}

ReleaseListRow is one release in a listing.

type ReleaseNotesResult

type ReleaseNotesResult struct {
	Release  string            `json:"release"`
	Since    string            `json:"since,omitempty"`
	Markdown string            `json:"markdown"`
	Change   release.ChangeSet `json:"change"`
	// File is set when the draft was written to disk.
	File string `json:"file,omitempty"`
}

ReleaseNotesResult is the generated draft plus the change set it came from.

type RemoteView

type RemoteView struct {
	Name                     string
	Type                     string
	Committed                bool
	Local                    bool
	Bound                    bool   // has a usable local binding on this machine
	Path                     string // filesystem binding
	Endpoint, Bucket, Prefix string
	Region, Addressing       string
	RequiredForPublication   bool
	// CredentialProfile is the credential-store entry an s3 remote uses on
	// this machine; empty means the default profile.
	CredentialProfile string
	// HasCredentials reports that a stored login exists for an s3 remote. It
	// never exposes the secret itself.
	HasCredentials bool
}

RemoteView is the merged committed + local view of one storage remote.

type RepairReport

type RepairReport struct {
	Rebuilt []string
	Refused []Finding
}

RepairReport lists what Repair rebuilt and what it refused to touch.

type Repo

type Repo struct {
	Root         string // working-tree top level (from git)
	GitDir       string
	GitCommonDir string
	Config       *domain.Repository
	Local        *domain.LocalConfig
	Domain       string // storageDomainID
	Git          *gitclient.Client
	Cache        *cache.Cache
	Paths        state.Paths
	Locks        *lock.Set
	// contains filtered or unexported fields
}

Repo is an opened FXVCS checkout.

func Open

func Open(ctx context.Context, start string, opts Options) (*Repo, error)

Open resolves the checkout containing start, loads and preflights the committed configuration, loads local configuration, and opens the cache. It does not open the SQLite databases; use State()/Ledger() lazily so read-only diagnostics never create or migrate them.

func (*Repo) CacheLimit

func (r *Repo) CacheLimit() int64

CacheLimit is the size this clone trims the host cache back to after an operation adds objects. Zero means no automatic trimming.

func (*Repo) CachePrune

func (r *Repo) CachePrune(ctx context.Context, targetBytes int64, dryRun bool) ([]CacheEviction, int, error)

CachePrune evicts least-recently-used unpinned objects until the cache is at or below targetBytes (0 = evict everything evictable). Pinned (pending publication) objects are never removed. dryRun only plans.

func (*Repo) CacheStatus

func (r *Repo) CacheStatus(ctx context.Context) (CacheSummary, error)

CacheStatus summarizes cache usage across all domains and pins.

func (*Repo) CacheVerify

func (r *Repo) CacheVerify(ctx context.Context, opts CacheVerifyOptions, progress func(CacheVerifyProgress)) (CacheVerifyReport, error)

CacheVerify re-reads cached objects and checks their bytes against their digests. This is the only operation that detects silent disk corruption: an object is normally verified when it is read, so an object that is never read can rot unnoticed until a deployment needs it.

It writes nothing unless Repair is set, and it holds the cache-prune lock only while removing objects, never while reading them.

func (*Repo) CatalogPath

func (r *Repo) CatalogPath() string

CatalogPath is the absolute path of .fxvcs/resources.yaml.

func (*Repo) ChunkPolicy

func (r *Repo) ChunkPolicy() (chunk.Policy, error)

ChunkPolicy returns the encoding policy for this repository.

func (*Repo) Close

func (r *Repo) Close() error

Close releases locks and databases.

func (*Repo) Content

func (r *Repo) Content(ctx context.Context, ptr pointer.Pointer) (Content, error)

Content resolves the storage plan for a pointer. For whole/1 this is pure local arithmetic. For a chunked encoding it needs the manifest object, which it takes from the cache or fetches from a configured remote, and which it validates against the pointer before trusting a single chunk digest.

func (*Repo) ContentDigests

func (r *Repo) ContentDigests(ctx context.Context, ptr pointer.Pointer) ([]string, error)

ContentDigests returns every object digest behind a pointer, or an error when the manifest cannot be resolved.

func (*Repo) ContentLocal

func (r *Repo) ContentLocal(ctx context.Context, ptr pointer.Pointer) (Content, error)

ContentLocal resolves the storage plan for a pointer using only what is already cached.

It differs from Content in one respect that matters here: a chunked pointer names its chunks in a manifest object, and Content fetches that manifest from a remote when it is missing. This reports ErrObjectNotCached instead, so a caller asking about content it may not have does not trigger a download by asking.

func (*Repo) Dehydrate

func (r *Repo) Dehydrate(ctx context.Context, sel Selection, progress ProgressFunc) ([]PathOutcome, error)

Dehydrate replaces each selected hydrated-clean working file with the exact pointer bytes of its index entry. A file whose clean result differs from the index pointer (hydrated-modified) is refused, as is a file whose object is neither cached (and pinned or published) nor re-ingestible.

func (*Repo) Discard

func (r *Repo) Discard(ctx context.Context, sel Selection, progress ProgressFunc) ([]PathOutcome, error)

Discard throws away the working changes to each selected asset, restoring the working file from the index pointer.

It is the only operation in this package whose purpose is to destroy bytes that exist nowhere else, so it is also the only one that is never implicit: nothing calls it as a step of something larger, and no repair, checkout, or hook path reaches it. A caller has to ask for it by name, having been told by the discard action (actions.go) exactly which assets it would affect.

The working file is restored in the form it currently has. A file holding real bytes is rewritten with the real bytes of the index pointer, so a texture stays a texture; a file holding a pointer to some other object — the conflict state — is rewritten with the index pointer, because materializing megabytes the user never asked to download would be a strange way to resolve a disagreement between two pointers. Either way the result is the state the index describes, which is what "discard my changes" means.

func (*Repo) Doctor

func (r *Repo) Doctor(ctx context.Context, opts DoctorOptions) ([]Finding, error)

Doctor reports every disagreement between the index, the working tree, state.db, the publication ledger, the cache, and the Git driver configuration. It is read-only: no database is created or migrated and no working file is written.

func (*Repo) EnsureContent

func (r *Repo) EnsureContent(ctx context.Context, ptr pointer.Pointer, progress func(fetched, total int)) (Content, error)

EnsureContent makes every object behind the pointer available in the local cache, fetching what is missing from configured remotes with bounded concurrency. No lock is held while it runs.

func (*Repo) FetchContent

func (r *Repo) FetchContent(ctx context.Context, ptr pointer.Pointer, progress ProgressFunc) (ObjectInfo, error)

FetchContent downloads every object behind a pointer into the local cache and reports what it took. It writes nothing to the working tree, which is what separates it from hydrate: it makes content readable, it does not decide what a file on disk should be.

func (*Repo) FetchObject

func (r *Repo) FetchObject(ctx context.Context, digest string) error

FetchObject brings an object into the local cache from the first remote in read order that has it, verifying the digest while streaming. Returns objectstore.ErrNotFound when no configured remote has it.

func (*Repo) FiveMDescriptor

func (r *Repo) FiveMDescriptor() (domain.ComponentDescriptor, error)

FiveMDescriptor returns the accepted component descriptor from the committed configuration, or a typed error pointing at `fxvcs init --profile fivem` when the repository is not a FiveM component.

func (*Repo) HasContent

func (r *Repo) HasContent(ctx context.Context, ptr pointer.Pointer) bool

HasContent reports whether every object behind the pointer is present locally. It does not read object bytes and never contacts a remote, so it is cheap enough for status listings; a chunked pointer whose manifest is not cached answers false.

func (*Repo) Hydrate

func (r *Repo) Hydrate(ctx context.Context, sel Selection, progress ProgressFunc) ([]PathOutcome, error)

Hydrate materializes the object behind each selected index pointer at its working path following the compare-and-swap sequence of docs/spec/checkout-consistency.md §2. It never overwrites a working file whose clean result differs from the index pointer (hydrated-modified) and never leaves a partially written destination.

func (*Repo) HydrationIntent

func (r *Repo) HydrationIntent(ctx context.Context, path string) (hydrated, known bool, err error)

HydrationIntent reports the recorded intent for a path. known is false when state.db does not exist or holds no row: the unhydrated default applies.

func (*Repo) Ingest

func (r *Repo) Ingest(ctx context.Context, content io.Reader, referrerPath string) (Ingested, error)

Ingest streams content into the local immutable cache under this repository's storage domain, pins the objects it creates (pending publication), records them in the shared publication ledger, and returns the deterministic pointer. It is the single ingestion path used by the Git clean filter and by `migrate`; it needs no network and is idempotent for identical bytes.

The encoding is chosen by chunk.DefaultPolicy, which is a property of the format generation rather than of this machine: identical bytes must produce an identical pointer everywhere, or Git would report a modification whenever a differently configured client restaged the file. Small objects stay whole/1 exactly as in Stage 1.

Ordering matters for crash safety: object bytes first (atomic rename), then pins, then ledger rows, and for chunked encodings the manifest object is written only after every chunk it names. A crash between steps leaves at worst an unpinned or unrecorded cached object, which repair/rebuild can reconcile; it never leaves a pointer whose objects are missing.

func (*Repo) IngestExpecting

func (r *Repo) IngestExpecting(ctx context.Context, content io.Reader, referrerPath string, expect pointer.Pointer) (Ingested, error)

IngestExpecting is Ingest for a caller that already knows what the content must hash to — re-deriving a working file from its own index pointer.

The hint never changes what is stored or what pointer comes back; it only lets the whole-blob path recognise that the object it is about to write is already cached, and skip writing a second copy of a file that can be several hundred megabytes. The stream is still read and hashed in full, so the content is proven, and a mismatch is reported rather than stored.

func (*Repo) Installed

func (r *Repo) Installed() format.Version

Installed returns the running binary version.

func (*Repo) Ledger

func (r *Repo) Ledger(ctx context.Context) (*state.Ledger, error)

Ledger opens (creating on demand) the shared publication ledger.

func (*Repo) LedgerIfExists

func (r *Repo) LedgerIfExists(ctx context.Context) (*state.Ledger, error)

LedgerIfExists opens the ledger without creating it.

func (*Repo) LoadResourceCatalog

func (r *Repo) LoadResourceCatalog() (cat *domain.ResourceCatalog, raw []byte, exists bool, err error)

LoadResourceCatalog reads and strictly validates the committed catalog. A missing file yields an empty catalog carrying this repository's ID and exists=false. raw holds the file bytes as read (nil when missing).

func (*Repo) Lock

func (r *Repo) Lock(ctx context.Context, level journal.Level, key string) (*lock.Handle, error)

Lock acquires a lock in the documented order with the configured timeout.

func (*Repo) LockTimeout

func (r *Repo) LockTimeout() time.Duration

LockTimeout returns the configured lock wait.

func (*Repo) ManagedEntries

func (r *Repo) ManagedEntries(ctx context.Context, sel Selection) (entries []IndexEntry, missing []string, err error)

ManagedEntries lists index entries whose effective attributes route them through the fxvcs filter, restricted to the selection. Unknown literal paths (not in the index or not managed) are returned in missing so callers can report them per item. Nothing is locked; the result is a snapshot.

func (*Repo) Migrate

func (r *Repo) Migrate(ctx context.Context, in MigrateInput) ([]MigrateOutcome, error)

Migrate converts selected index entries that are ordinary blobs into pointers without rewriting history: for each path it ingests the working file (r.Ingest: cache, pin, ledger) and then runs `git add --renormalize -- <path>` so the clean filter stages the identical deterministic pointer while the working tree keeps the hydrated bytes; the hydration state row is committed as hydrated-clean through the operation journal. Every path is validated (in index, tracked by a managed rule, clean against the index) before the first change. Already-pointer entries are reported as skipped.

func (*Repo) NewLockSet

func (r *Repo) NewLockSet() *lock.Set

NewLockSet makes a lock.Set over the same lock files as r.Locks.

The directory is taken from the existing set rather than recomputed: these are the files that exclude other processes, and a set rooted anywhere else would take locks nobody else looks at — mutual exclusion lost silently, with every test still passing.

func (*Repo) Now

func (r *Repo) Now() time.Time

Now returns the clock.

func (*Repo) ObjectsPublish

func (r *Repo) ObjectsPublish(ctx context.Context, remotes []string, progress PublishProgress) (published, failed []PublishOutcome, err error)

ObjectsPublish uploads every recorded object that lacks a publication record on the target remotes, records publication in the ledger, and settles pins whose required remotes are all satisfied. It never pushes Git refs. It first computes the full plan (so a UI can show pending items), then uploads with bounded concurrency; ledger writes are serialized. No lock is held during transfers.

func (*Repo) ObjectsStatus

func (r *Repo) ObjectsStatus(ctx context.Context) ([]ObjectState, error)

ObjectsStatus lists every locally ingested object with per-remote state.

func (*Repo) OpenContent

func (r *Repo) OpenContent(ctx context.Context, ptr pointer.Pointer) (io.ReadCloser, error)

OpenContent returns a reader over the whole file behind a pointer, reconstructed from the local cache and verified as it streams: every chunk is checked against its own digest, the total length against the pointer size, and — for chunked encodings — the concatenation against the pointer oid at EOF. Callers must treat any error as "no valid content".

It does not fetch; call EnsureContent first.

func (*Repo) OpenContentAt

func (r *Repo) OpenContentAt(ctx context.Context, ptr pointer.Pointer, offset, length int64) (io.ReadCloser, error)

OpenContentAt returns a reader over the content behind a pointer, from the local cache only, optionally restricted to a byte range. offset 0 with length 0 (or length covering the rest) is the whole content.

The returned reader outlives the Repo: it holds open cache files, not repository state.

func (*Repo) Prefetch

func (r *Repo) Prefetch(ctx context.Context, ptrs []pointer.Pointer, fetched func(digest string))

Prefetch warms the cache for many pointers at once.

Materializing a file is two different kinds of work: fetching its objects, which is network-bound and independent per file, and writing it into the working tree, which is a compare-and-swap against the index and must stay serialized per path. Doing both in one loop makes the network work sequential too, so loading 600 assets from a remote store costs 600 round trips in series — minutes of waiting for a link that could have been saturated.

Prefetch does the network half for the whole selection first, with bounded concurrency and shared deduplication (two assets that share a chunk fetch it once). It is best effort: an object that cannot be fetched is left alone, and the per-path operation reports it with the right error and outcome.

func (*Repo) PrefetchProgress

func (r *Repo) PrefetchProgress(ctx context.Context, ptrs []pointer.Pointer, fetched func(digest string), onBytes func(digest string, delta int64))

PrefetchProgress is Prefetch with byte-level reporting.

func (*Repo) PublicationMissing

func (r *Repo) PublicationMissing(ctx context.Context, ptr pointer.Pointer) ([]string, error)

PublicationMissing returns the requiredForPublication remotes that hold no publication record for digest. When a required remote is bound on this machine and the ledger has no record, the remote is probed (bounded, no lock held) and a positive answer is recorded so a clone that did not publish the object itself is not blocked from pushing history containing it. ptr supplies the object metadata for the record.

func (*Repo) PublicationMissingMany

func (r *Repo) PublicationMissingMany(ctx context.Context, ptrs []pointer.Pointer) (map[string][]string, error)

PublicationMissingMany is the batched form of PublicationMissing: it answers the same question for many pointers with a bounded number of round trips instead of one per pointer.

The pre-push barrier asks this about every asset a push touches. Asked one pointer at a time against a network object store, that is one sequential HTTP request per asset before a single byte is uploaded — tens of seconds for a few hundred assets on an ordinary internet link, with nothing to show for it. Batched, it is one ledger scan plus one bulk existence query per remote.

The returned map is keyed by pointer oid.

func (*Repo) PublicationSummary

func (r *Repo) PublicationSummary(ctx context.Context) (PublicationSummary, error)

PublicationSummary reads aggregate publication state without inspecting manifests, the cache, the working tree, or any remote store.

func (*Repo) Publish

func (r *Repo) Publish(ctx context.Context, opts PublishOptions) (published, failed []PublishOutcome, err error)

Publish is ObjectsPublish with streamed events and bounded concurrency.

func (*Repo) ReadOrder

func (r *Repo) ReadOrder() []string

ReadOrder returns remote names in read preference order: local ReadOrder first, then remaining remotes in committed/local order.

func (*Repo) RecordHydrated

func (r *Repo) RecordHydrated(ctx context.Context, path, digest string, size int64) error

RecordHydrated notes, best effort, that the working file at path holds the real bytes of digest (the clean filter just ingested them from it). The row is only written when the path lock is free; a busy lock means an operation on that path is in flight and will write the authoritative row.

func (*Repo) Remotes

func (r *Repo) Remotes() []RemoteView

Remotes returns every known remote, committed first then local-only, in a stable order.

func (*Repo) Repair

func (r *Repo) Repair(ctx context.Context, opts DoctorOptions) (RepairReport, error)

Repair rebuilds only safe derived state under the checkout-worktree lock: state.db rows from facts (index + working scan), resolution of interrupted operations (keep-dirty is never overwritten), ledger rows for cached objects the index references, pointer re-materialization for missing working files, and the Git driver configuration and pre-push hook. Every hydrated-modified or conflict path is refused and listed. No remote is contacted while a lock is held.

func (*Repo) RequiredRemotes

func (r *Repo) RequiredRemotes() []string

RequiredRemotes returns names of remotes that must hold every object before Git refs may become remotely reachable.

func (*Repo) ResourcesSet

func (r *Repo) ResourcesSet(ctx context.Context, in ResourcesSetInput) (*ResourcesSetOutput, error)

ResourcesSet updates activation and ordering of one entry and writes the catalog atomically. It never commits.

func (*Repo) ResourcesSync

func (r *Repo) ResourcesSync(ctx context.Context, in ResourcesSyncInput) (*ResourcesSyncOutput, error)

ResourcesSync scans the source root, merges the discovered resources into .fxvcs/resources.yaml (preserving operator-owned fields, tombstoning missing entries), and writes the catalog atomically. It never commits. It is idempotent: a second run reports no changes and leaves the file byte-identical.

func (*Repo) ResourcesValidate

func (r *Repo) ResourcesValidate(ctx context.Context, in ResourcesValidateInput) (*ResourcesValidateOutput, error)

ResourcesValidate re-scans the worktree source root, diffs the committed catalog against the rescan (undeclared, missing, stale entries), runs release validation (pending/missing entries, names, ordering cycles, persistent paths, mutableMode) and schema validation of the YAML. It is what release creation runs against each pinned tree. Scan failures (including sandbox violations) are returned as a typed error; catalog findings are returned in Problems together with ErrCatalogNotReleasable.

func (*Repo) SaveLocal

func (r *Repo) SaveLocal() error

SaveLocal persists r.Local.

func (*Repo) Scan

func (r *Repo) Scan(ctx context.Context, minBytes int64) ([]ScanCandidate, error)

Scan lists tracked and untracked (not ignored) working-tree files of at least minBytes with whether a managed rule already applies. It reads only.

func (*Repo) ScanResources

ScanResources runs discovery and sandboxed manifest evaluation over the worktree using the accepted descriptor. Failures are typed *ResourceScanError; a manifest failure names the manifest.

func (*Repo) ScanResourcesTree

func (r *Repo) ScanResourcesTree(ctx context.Context, desc domain.ComponentDescriptor) (discovery.ScanResult, error)

ScanResourcesTree is ScanResources returning the manifests FXServer would walk past as well, so callers can report them.

func (*Repo) SetCacheLimit

func (r *Repo) SetCacheLimit(ctx context.Context, limitBytes int64) error

SetCacheLimit records the automatic-trim budget in local configuration. It is a machine-local preference: how much disk this computer is willing to spend on cached asset data is not a property of the repository.

func (*Repo) Setup

func (r *Repo) Setup(ctx context.Context, in SetupInput) (SetupResult, error)

Setup configures this clone for FXVCS: it makes sure a launcher binary exists at the launcher path (copying the running executable there when the path is empty), writes the repository-local driver configuration, installs the managed pre-push hook without overwriting a user hook, records the launcher in local config, and creates the local databases so their schema exists before the first filter invocation. It is idempotent and never commits.

func (*Repo) StatContent

func (r *Repo) StatContent(ctx context.Context, ptr pointer.Pointer) (ObjectInfo, error)

StatContent reports what is known locally about a pointer's content without reading or fetching it. It answers the question an interface has to settle before it offers a comparison at all: can this be read right now.

func (*Repo) State

func (r *Repo) State(ctx context.Context) (*state.DB, error)

State opens (creating on demand) the per-worktree hydration database. Callers must hold LockCheckoutWorktree or a LockPath before mutating rows.

func (*Repo) StateIfExists

func (r *Repo) StateIfExists(ctx context.Context) (*state.DB, error)

StateIfExists opens the hydration database without creating it.

func (*Repo) Status

func (r *Repo) Status(ctx context.Context, sel Selection) ([]PathStatus, []PathOutcome, error)

Status derives the consistency state of every selected managed path from the index pointer, the working file, and the state row. Unchanged files are not re-hashed: the stat fingerprint recorded in state.db decides whether the recorded digest is still trustworthy. Rows re-derived here are written back opportunistically (per-path lock, no wait) so the next status is fast.

func (*Repo) StorageAdd

func (r *Repo) StorageAdd(ctx context.Context, in StorageAddInput) (RemoteView, error)

StorageAdd registers a storage remote. By default it declares the non-secret remote descriptor in the committed configuration (if not already declared) so every clone shares it, and binds the machine-specific location in local configuration. With Local it only records the clone-local remote. It never commits and never writes credentials or paths into committed files.

func (*Repo) StorageLogin

func (r *Repo) StorageLogin(ctx context.Context, in StorageLoginInput) (StorageLoginResult, error)

StorageLogin stores (or forgets) the credentials for an S3-compatible remote.

The secret goes to the user configuration directory with 0600 permissions, never to the repository: committed configuration is shared with everyone who can clone, and Git's administrative directory travels with copies of the clone. Nothing is written to the working tree and nothing is committed.

func (*Repo) StorageProfiles

func (r *Repo) StorageProfiles() ([]string, string, error)

StorageProfiles lists the credential-store entries this machine holds. It returns names only; secrets never leave the store.

func (*Repo) StorageStats

func (r *Repo) StorageStats(ctx context.Context, sel Selection, opts StorageStatsOptions) (StorageStats, error)

StorageStats measures deduplication across the current index.

func (*Repo) StorageTest

func (r *Repo) StorageTest(ctx context.Context, name string) ([]objectstore.Capability, error)

StorageTest runs the backend capability probe for one remote.

func (*Repo) Store

func (r *Repo) Store(name string) (objectstore.Store, RemoteView, error)

Store returns the object store client for a remote name.

func (*Repo) TopSharedObjects

func (r *Repo) TopSharedObjects(ctx context.Context, sel Selection, limit int) ([]SharedObject, error)

TopSharedObjects lists the most-reused objects, for a report that wants to name what the sharing is actually made of.

func (*Repo) Track

func (r *Repo) Track(ctx context.Context, in TrackInput) (TrackResult, error)

Track adds rules to the managed block. It never rewrites history: the rules take effect for the next `git add`.

func (*Repo) TrackingCheck

func (r *Repo) TrackingCheck(ctx context.Context, rel string) (TrackingCheck, error)

TrackingCheck runs git check-attr for one repository-relative path and attributes the effective filter rule to a line of the root .gitattributes: every line that mentions the filter attribute is copied into a temporary attributes file under a unique marker attribute and evaluated by Git itself (core.attributesFile has top-level pattern semantics), so pattern matching is exactly Git's. The last matching line wins, as in Git.

func (*Repo) TryLock

func (r *Repo) TryLock(ctx context.Context, level journal.Level, key string) (*lock.Handle, error)

TryLock acquires without waiting, for callers whose work is optional when something else already holds the lock.

It exists so that every acquisition in this package goes through the context's lock set. A call that reached for r.Locks directly would put concurrent paths back on the one journal.Sequence that per-worker sets exist to keep them off — and it would do so from the places least likely to be covered by a test, because they are the ones that only run when a path turns out to need nothing done to it.

func (*Repo) Untrack

func (r *Repo) Untrack(ctx context.Context, in TrackInput) (UntrackResult, error)

Untrack removes rules from the managed block and reports index entries that are pointers no longer covered by any rule. It hydrates nothing.

func (*Repo) Upgrade

func (r *Repo) Upgrade(ctx context.Context, mode string, repairLauncher ...bool) (UpgradeResult, error)

Upgrade computes the plan that brings FXVCS-owned content of this repository and clone to the running binary's generation and, in apply mode, executes it step by step. Check and plan modes are read-only (apart from asking the launcher binary for its version). Apply changes only FXVCS-owned content guarded by ExpectedBefore digests, never commits, stops at the first conflict, and can be re-run after an interruption: the remaining steps are recomputed from the current state.

func (*Repo) Verify

func (r *Repo) Verify(ctx context.Context, sel Selection, opts VerifyOptions) (checked int, issues []VerifyIssue, err error)

Verify checks, for every selected managed index entry: pointer syntax and whole/1 manifest derivation, storage domain, the cached object's size and digest (full read), and — with Remote — presence on every required remote. It writes nothing. Checked counts index entries examined.

type RescanFinding

type RescanFinding struct {
	RepositoryID string                      `json:"repositoryID"`
	Name         string                      `json:"name"`
	Commit       string                      `json:"commit"`
	Accepted     domain.ComponentDescriptor  `json:"accepted"`
	AcceptedFrom string                      `json:"acceptedFrom"`
	Detected     *domain.ComponentDescriptor `json:"detected,omitempty"`
	Mount        string                      `json:"mount"`
	// ProposedMount is set when the recorded mount no longer fits the layout.
	ProposedMount string `json:"proposedMount,omitempty"`
	// Agrees is false when detection disagrees with the accepted descriptor or
	// the mount no longer fits it.
	Agrees  bool     `json:"agrees"`
	Notes   []string `json:"notes,omitempty"`
	Updated bool     `json:"updated,omitempty"`
}

RescanFinding is one component's layout review.

type ResourceNotFoundError

type ResourceNotFoundError struct {
	Path  string
	Known []string
}

ResourceNotFoundError names the unknown path and the known catalog paths.

func (*ResourceNotFoundError) Error

func (e *ResourceNotFoundError) Error() string

func (*ResourceNotFoundError) Is

func (e *ResourceNotFoundError) Is(target error) bool

type ResourceScanError

type ResourceScanError struct {
	Manifests []string
	Err       error
}

ResourceScanError is the typed failure of discovery/manifest evaluation over the worktree source root. Manifests lists the offending manifest files (tree-relative) when the failure is attributable to one.

func (*ResourceScanError) Error

func (e *ResourceScanError) Error() string

func (*ResourceScanError) Is

func (e *ResourceScanError) Is(target error) bool

func (*ResourceScanError) Unwrap

func (e *ResourceScanError) Unwrap() error

type ResourcesSetInput

type ResourcesSetInput struct {
	ResourcePath string
	Activation   domain.Activation // "" = unchanged
	After        []string
	Before       []string
}

ResourcesSetInput edits one catalog entry identified by its literal path. nil After/Before leave ordering unchanged; a non-nil empty list clears it.

type ResourcesSetOutput

type ResourcesSetOutput struct {
	Resource domain.CatalogResource
	// Warnings names after/before references that no local resource (name or
	// provide) satisfies. They are accepted: a component may order against
	// resources of other components or the runtime; the stack validates
	// names globally.
	Warnings []string
	Written  bool
}

ResourcesSetOutput is the entry after the edit.

type ResourcesSyncInput

type ResourcesSyncInput struct {
	// NewActivation applies to newly discovered resources: pending (default,
	// also when empty), enabled, or disabled. Ignored when FromCfg is set.
	NewActivation domain.Activation
	// FromCfg is a server.cfg whose ensure/start directives (followed through
	// exec) supply activation for resources without a decision: new entries
	// and entries still pending become enabled when the cfg starts their
	// name; every other new entry stays pending. Existing enabled/disabled
	// entries are never changed.
	FromCfg string
}

ResourcesSyncInput configures ResourcesSync.

type ResourcesSyncOutput

type ResourcesSyncOutput struct {
	CatalogPath string   // repository-relative
	Added       []string // new entries
	Updated     []string // refreshed manifest-derived fields or revived tombstones
	Missing     []string // status missing (never deleted)
	Pending     []string // every entry left with activation pending
	Enabled     []string // entries whose activation was set by --from-cfg
	Unchanged   int
	Written     bool     // the file changed on disk
	Warnings    []string // skipped manifests and cfg import warnings
	Report      catalog.Report
	Catalog     *domain.ResourceCatalog
}

ResourcesSyncOutput reports what the sync did.

type ResourcesValidateInput

type ResourcesValidateInput struct {
	// KnownNames are resource names supplied by other components, the runtime
	// catalog, or externals. after/before may reference them without a
	// warning.
	KnownNames []string
}

ResourcesValidateInput tunes ResourcesValidate.

type ResourcesValidateOutput

type ResourcesValidateOutput struct {
	CatalogPath string
	Valid       bool
	Resources   int
	Problems    []catalog.Problem
	Warnings    []string
	Diff        catalog.DiffReport
}

ResourcesValidateOutput lists every finding. Valid is true when Problems is empty. Warnings are advisory (ordering references that only the composition can resolve).

type RuntimeResourcesSyncInput

type RuntimeResourcesSyncInput struct {
	// FromCfg is a server.cfg to read `ensure`/`start` directives from.
	FromCfg string
}

RuntimeResourcesSyncInput seeds the coordination runtime catalog.

type RuntimeResourcesSyncResult

type RuntimeResourcesSyncResult struct {
	File string `json:"file"`
	// Proposed are entries added as pending for review.
	Proposed []string `json:"proposed"`
	// Matched are cfg names already supplied by a component repository; they
	// belong to the component and must not be duplicated here.
	Matched []string `json:"matched"`
	// Existing are names already present in the runtime catalog.
	Existing  []string `json:"existing"`
	Files     []string `json:"files,omitempty"`
	Warnings  []string `json:"warnings,omitempty"`
	Written   bool     `json:"written"`
	Resources int      `json:"resources"`
}

RuntimeResourcesSyncResult reports the proposal.

type ScanCandidate

type ScanCandidate struct {
	Path    string
	Bytes   int64
	Tracked bool
}

ScanCandidate is one large working-tree file.

type Selection

type Selection struct {
	Paths []string
	Glob  bool
}

Selection names the paths an operation acts on. Empty Paths selects every managed path in the index. With Glob, entries are Git pathspecs (glob syntax); otherwise they are literal repository-relative paths.

type SetupInput

type SetupInput struct {
	// LauncherPath is the absolute driver launcher to install; empty selects
	// the launcher already recorded in local config, else the per-user
	// default (filter.DefaultLauncherPath).
	LauncherPath string
	// RepairLauncher permits a trusted candidate to replace different bytes
	// reporting the same semantic version. Normal newest-wins setup refuses
	// that ambiguous case.
	RepairLauncher bool
}

SetupInput configures Setup.

type SetupResult

type SetupResult struct {
	LauncherPath string
	// LauncherInstalled is true when the trusted launcher candidate was
	// installed or updated at LauncherPath.
	LauncherInstalled bool
	LauncherOutcome   LauncherOutcome
	// LegacyLauncherOutcome reports compatibility maintenance of the exact
	// former macOS default. Arbitrary custom paths are never treated as legacy.
	LegacyLauncherPath    string
	LegacyLauncherOutcome LauncherOutcome
	// ConfigKeys lists the repository-local git config keys written.
	ConfigKeys []string
	HookPath   string
	// HookInstalled is true when the managed hook was written or refreshed.
	HookInstalled bool
	// HookForeign is true when a hook not managed by fxvcs occupies pre-push;
	// HookInstructions then tells the user how to chain it. Not an error.
	HookForeign      bool
	HookInstructions string
	// StateCreated / LedgerCreated report databases created by this call.
	StateCreated  bool
	LedgerCreated bool
}

SetupResult reports what Setup did.

type SharedObject

type SharedObject struct {
	Digest     string
	Bytes      int64
	Users      int
	SavedBytes int64
	Paths      []string
}

SharedObject is one stored object more than one asset uses.

type StackAddInput

type StackAddInput struct {
	// Remote is the component's Git URL.
	Remote string
	// Ref is the branch or tag to follow (default: the remote's default branch).
	Ref string
	// Mount overrides the proposed mount.
	Mount string
	// Alias resolves a display-name collision.
	Alias string
	// Optional marks the component not required for a release.
	Optional bool
}

StackAddInput registers one component repository.

type StackAddResult

type StackAddResult struct {
	Component ComponentProposal `json:"component"`
	File      string            `json:"file"`
	Warnings  []string          `json:"warnings,omitempty"`
}

StackAddResult reports the registration.

type StackInitInput

type StackInitInput struct {
	// Path is any directory inside the Git repository to use.
	Path string
	// Name is the stack display name (default: the directory name).
	Name string
	// Profile is the composition profile (default: fivem).
	Profile string
	// Adopt accepts an existing fxvcs.yaml instead of failing.
	Adopt bool
}

StackInitInput describes the coordination repository to create or adopt.

type StackInitResult

type StackInitResult struct {
	Root    string `json:"root"`
	StackID string `json:"stackID"`
	Name    string `json:"name"`
	Profile string `json:"profile"`
	File    string `json:"file"`
	Adopted bool   `json:"adopted"`
}

StackInitResult reports what init did.

func StackInit

func StackInit(ctx context.Context, in StackInitInput, opts Options) (*StackInitResult, error)

StackInit creates or adopts a coordination repository. It writes one reviewable file and never commits: the stack becomes real when a human commits it, which is the whole contract of a GitOps control plane.

type StackRescanResult

type StackRescanResult struct {
	Findings []RescanFinding `json:"findings"`
	Changed  bool            `json:"changed"`
	File     string          `json:"file,omitempty"`
}

StackRescanResult reports the review.

type StackStatusResult

type StackStatusResult struct {
	StackID       string            `json:"stackID"`
	Name          string            `json:"name"`
	Profile       string            `json:"profile"`
	Root          string            `json:"root"`
	Components    []ComponentStatus `json:"components"`
	Releases      int               `json:"releases"`
	LatestRelease string            `json:"latestRelease,omitempty"`
	Environments  []string          `json:"environments"`
	Targets       []string          `json:"targets"`
}

StackStatusResult is the whole composition at a glance.

type StackSyncResult

type StackSyncResult struct {
	Components []ComponentSync `json:"components"`
	Fetched    int             `json:"fetched"`
	Updated    int             `json:"updated"`
	Failed     int             `json:"failed"`
}

StackSyncResult reports every component fetch.

type StackValidateResult

type StackValidateResult struct {
	Valid      bool              `json:"valid"`
	Components []ComponentStatus `json:"components"`
	Resources  []PlannedResource `json:"resources"`
	Enabled    int               `json:"enabled"`
	Disabled   int               `json:"disabled"`
	Problems   []stack.Problem   `json:"problems"`
	Warnings   []string          `json:"warnings,omitempty"`
}

StackValidateResult is the composition report.

type StorageAddInput

type StorageAddInput struct {
	Name string
	Type string // filesystem | s3
	Path string // filesystem: absolute directory on this machine
	// S3 descriptor. Bucket, Endpoint, Prefix, Region, and Addressing are
	// non-secret and go into the committed configuration for a shared remote;
	// credentials never do (see StorageLogin).
	Bucket     string
	Endpoint   string
	Prefix     string
	Region     string
	Addressing string
	// Local registers a clone-local remote only (not written to the committed
	// configuration). When false the remote is declared in
	// .fxvcs/repository.yaml if absent (a reviewable working-tree edit; never
	// committed by FXVCS) and its machine-specific binding is stored locally.
	Local                  bool
	RequiredForPublication bool
}

StorageAddInput describes a remote to register.

type StorageLoginInput

type StorageLoginInput struct {
	Remote          string
	AccessKeyID     string
	SecretAccessKey string
	SessionToken    string
	// Profile overrides the credential-store entry name. Empty means the
	// default, "<storageDomainID>/<remote>", which lets several clones of the
	// same storage domain share one login.
	Profile string
	// Forget removes the stored entry instead of writing one.
	Forget bool
}

StorageLoginInput records an object-store identity for one remote on this machine. The secret arrives as a value from the caller: no operation in this package reads stdin or prompts, so the CLI collects it (without echo) and hands it over.

type StorageLoginResult

type StorageLoginResult struct {
	Remote          string
	Profile         string
	CredentialsFile string
	AccessKeyID     string
	Removed         bool
}

StorageLoginResult reports where the identity was stored. It never contains the secret, and the access key id is returned only so a person can confirm they stored the one they meant to.

type StorageStats

type StorageStats struct {
	// Assets is every tracked path in the index; Contents is how many
	// distinct files they are.
	Assets   int
	Contents int

	// LogicalBytes is what the assets weigh laid out as ordinary files, one
	// copy per path. StoredBytes is what they actually occupy as objects.
	LogicalBytes int64
	StoredBytes  int64

	// The saving splits into two mechanisms, which are worth telling apart
	// because they scale differently: whole files that are byte-identical,
	// and pieces shared between files that merely resemble each other (the
	// same asset at two versions, or two variants of one texture).
	IdenticalFiles      int
	IdenticalFileBytes  int64
	FilesSharingParts   int
	SharedPartBytes     int64
	SharedObjects       int
	ChunkedAssets       int
	WholeAssets         int
	LargestSharedObject int64

	// Unresolved counts assets whose object manifest is not available
	// locally, so their pieces could not be examined. They are still counted
	// in Assets and LogicalBytes; the saving figures are a lower bound while
	// this is non-zero.
	Unresolved int
}

StorageStats is what content addressing is buying this repository, measured against the only honest baseline: storing every tracked file's bytes once per path, which is what a plain shared folder or an FTP upload does.

It is deliberately a point-in-time measurement of one repository. Savings across repositories are not a thing this can report and not a thing FXVCS does: one repository is one storage domain, content is never deduplicated across access boundaries, and a number that pretended otherwise would be describing a system with different security properties.

func (StorageStats) SavedBytes

func (s StorageStats) SavedBytes() int64

SavedBytes is the difference between laying every path out as its own file and storing the objects behind them.

func (StorageStats) SavedFraction

func (s StorageStats) SavedFraction() float64

SavedFraction is the saving as a fraction of the logical size.

type StorageStatsOptions

type StorageStatsOptions struct {
	// Fetch allows resolving object manifests that are not cached locally,
	// which costs one request per unexamined asset. Off by default: a report
	// should not quietly download a repository's worth of metadata.
	Fetch bool
}

StorageStatsOptions configures the measurement.

type TargetPlanObservations

type TargetPlanObservations struct {
	Supervisor        reconcile.SupervisorCapabilities
	PlayerCount       *int
	ActivationAllowed bool
}

TargetPlanObservations are host facts that cannot be inferred from AgentConfig. Apply supplies them from the selected typed supervisor and an injected activation-window evaluator; dry-run callers omit them and every observation-dependent gate stays closed.

type TargetResult

type TargetResult struct {
	Name        string `json:"name"`
	File        string `json:"file"`
	Release     string `json:"release"`
	Environment string `json:"environment"`
	AgentID     string `json:"agentID"`
	Authority   string `json:"authority"`
	RuntimeRef  string `json:"runtimeRef"`
	Keep        int    `json:"keep"`
	// SecretProvider is the default provider alias; provider implementations,
	// endpoints, and values stay on the agent.
	SecretProvider string `json:"secretProvider"`
	Created        bool   `json:"created,omitempty"`
	Changed        bool   `json:"changed,omitempty"`
	// PreviousRelease is what the target wanted before this change.
	PreviousRelease string `json:"previousRelease,omitempty"`
	// ReleaseExists reports whether the desired release record is present here.
	ReleaseExists bool `json:"releaseExists"`
	// Enabled counts the resources the desired release starts.
	Enabled int `json:"enabled,omitempty"`
	// EnvironmentRevision is the revision of the referenced environment.
	EnvironmentRevision int      `json:"environmentRevision,omitempty"`
	Warnings            []string `json:"warnings,omitempty"`
}

TargetResult is one target's desired state.

type TargetSetInput

type TargetSetInput struct {
	Name string
	// Release is the desired release. Promotion and rollback are both this.
	Release string
	// Environment, AgentID, RuntimeRef, Keep, and SecretProvider are required
	// when the target is created and optional afterwards.
	Environment    string
	AgentID        string
	RuntimeRef     string
	Keep           int
	SecretProvider string
}

TargetSetInput creates or updates one target's desired state.

type TrackInput

type TrackInput struct {
	// Patterns are literal repository-relative paths, or gitattributes glob
	// patterns when Glob is true.
	Patterns []string
	Glob     bool
	// Force allows a broad glob that would capture known source formats.
	Force bool
}

TrackInput selects rules to add or remove.

type TrackResult

type TrackResult struct {
	RulesAdded   []string
	RulesPresent []string
	Changed      bool
}

TrackResult reports the rules added to the managed block.

type TrackingCheck

type TrackingCheck struct {
	File          string
	Tracked       bool
	MatchedRule   string
	RuleSource    string
	AttributesRaw string
}

TrackingCheck explains the effective rule for one path.

type UntrackResult

type UntrackResult struct {
	RulesRemoved []string
	RulesMissing []string
	// PathsRequiringHydration are index entries that were pointers under a
	// removed rule and match no remaining rule; they must be hydrated before
	// they can be staged as ordinary blobs. Nothing is hydrated here.
	PathsRequiringHydration []string
	Changed                 bool
}

UntrackResult reports rules removed from the managed block.

type UpgradeResult

type UpgradeResult struct {
	UpToDate            bool
	Steps               []UpgradeStep
	Applied             bool
	AppliedSteps        []UpgradeStep
	Notes               []string
	InstalledVersion    string
	MinimumFXVCSVersion string
	LauncherPath        string
}

UpgradeResult is the plan (and, for apply, the outcome).

type UpgradeStep

type UpgradeStep struct {
	Kind           string
	Target         string
	FromVersion    string
	ToVersion      string
	ExpectedBefore string
	Description    string
}

UpgradeStep is one planned change. ExpectedBefore is the sha256 of the managed content the step will replace ("" when nothing exists yet); apply re-reads and refuses when it no longer matches.

type VerifyIssue

type VerifyIssue struct {
	Path    string
	Digest  string
	Kind    IssueKind
	Message string
}

VerifyIssue is one verification finding.

type VerifyOptions

type VerifyOptions struct {
	// Remote also checks that every requiredForPublication remote holds the
	// object (bounded Has() probes; no lock is held).
	Remote bool
}

VerifyOptions configures Verify.

Jump to

Keyboard shortcuts

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