catalog

package
v0.1.21 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package catalog provides tool catalog schema, caching, and search operations.

This package implements Layer 3 (Discovery) operations:

  • Fetch: Download catalog from registry servers
  • Cache: Store catalog locally with expiration
  • Search: Find tools by name, description, or capabilities

Security Boundary (CRITICAL)

This package is for DISCOVERY and DISPLAY ONLY.

Catalog data must NEVER influence:

  • Which binary gets executed
  • Whether a binary is considered verified
  • What digest is expected
  • What signer identity is trusted

The lockfile and Sigstore verification are the ONLY security sources of truth. Catalog provides publisher names and descriptions for display purposes only.

This package MUST NOT be imported by:

  • internal/dispatch (tool execution)
  • internal/collector (collector execution)
  • internal/tool (tool resolution)
  • internal/component (component management)

Only CLI-layer code (cmd/epack/toolcmd/catalog.go) should import this package.

Index

Constants

View Source
const (
	// CatalogFileName is the name of the cached catalog file.
	CatalogFileName = "catalog.json"

	// MetaFileName is the name of the catalog metadata file.
	MetaFileName = "catalog.json.meta"

	// CacheDirName is the epack cache directory name.
	CacheDirName = "epack"
)
View Source
const (
	MetaStatusOK          = schema.MetaStatusOK          // Successful fetch, catalog updated
	MetaStatusNotModified = schema.MetaStatusNotModified // 304 response, cache still valid
	MetaStatusError       = schema.MetaStatusError       // Fetch failed
)
View Source
const (
	MatchExact     = schema.MatchExact     // Exact name match
	MatchPrefix    = schema.MatchPrefix    // Name starts with query
	MatchSubstring = schema.MatchSubstring // Name, description, or publisher contains query
)
View Source
const (
	KindCollector = componenttypes.KindCollector
	KindTool      = componenttypes.KindTool
	KindRemote    = componenttypes.KindRemote
	KindUtility   = componenttypes.KindUtility
)
View Source
const DefaultCatalogURL = "https://registry.epack.dev/catalog.json"

DefaultCatalogURL is the default catalog URL.

View Source
const FetchTimeout = limits.DefaultHTTPTimeout

FetchTimeout is the maximum time to wait for catalog fetch. Uses the central HTTP timeout limit for consistency.

View Source
const GitHubHTTPSPrefix = "https://github.com/"

GitHubHTTPSPrefix is the required prefix for GitHub repository URLs.

View Source
const MetaVersion = schema.MetaVersion

MetaVersion is the current meta file version.

View Source
const SchemaVersion = schema.SchemaVersion

SchemaVersion is the current catalog schema version.

Variables

View Source
var ErrNoCatalog = errors.E(errors.CatalogNotFound, "no cached catalog found; run 'epack tool catalog refresh'", nil)

ErrNoCatalog is returned when no cached catalog exists.

View Source
var ErrNoMeta = errors.E(errors.CatalogMetaNotFound, "no catalog metadata found", nil)

ErrNoMeta is returned when no catalog metadata exists.

View Source
var ErrNotFound = errors.E(errors.ComponentNotFound, "component not found in catalog", nil)

ErrNotFound is returned when a component is not found in the catalog.

Functions

func CatalogPath

func CatalogPath() (string, error)

CatalogPath returns the full path to the cached catalog file.

func ClearCache

func ClearCache() error

ClearCache removes the cached catalog and metadata.

func Dir

func Dir() (string, error)

Dir returns the epack cache directory path. Uses XDG_CACHE_HOME on Unix, or platform-appropriate defaults.

Precedence:

  1. $XDG_CACHE_HOME/epack (if XDG_CACHE_HOME set)
  2. ~/.cache/epack (Unix)
  3. %LOCALAPPDATA%\epack\cache (Windows)

func Exists

func Exists() bool

Exists returns true if a cached catalog exists.

func MetaPath

func MetaPath() (string, error)

MetaPath returns the full path to the catalog metadata file.

func WriteCatalog

func WriteCatalog(catalog *Catalog) error

WriteCatalog writes the catalog to the cache directory. Creates the cache directory if it doesn't exist.

SECURITY: Uses safefile.OpenForWrite to prevent symlink attacks. O_NOFOLLOW atomically refuses to follow symlinks at file creation time, preventing attackers from swapping files with symlinks.

Note: We don't validate the entire cache path for symlinks because system symlinks (e.g., /var -> /private/var on macOS) are legitimate.

func WriteMeta

func WriteMeta(meta *CatalogMeta) error

WriteMeta writes the catalog metadata file. Creates the cache directory if it doesn't exist.

SECURITY: Uses safefile.OpenForWrite to prevent symlink attacks. O_NOFOLLOW atomically refuses to follow symlinks at file creation time, preventing attackers from swapping files with symlinks.

Types

type Catalog

type Catalog = schema.Catalog

Catalog is the component catalog schema v1. This is INFORMATIONAL ONLY - never use for security decisions.

func ParseCatalog

func ParseCatalog(data []byte) (*Catalog, error)

ParseCatalog parses catalog JSON with tolerant decoding. Unknown fields are silently ignored for forward compatibility.

func ReadCatalog

func ReadCatalog() (*Catalog, []string, error)

ReadCatalog reads the cached catalog, enforcing size limits. Returns ErrNoCatalog if no cached catalog exists.

SECURITY: Uses safefile.ReadFile to refuse symlinks, preventing an attacker from swapping the cache file with a symlink to read arbitrary files or cause the application to process attacker-controlled data.

type CatalogComponent

type CatalogComponent = schema.CatalogComponent

CatalogComponent contains display information about a component. NOTE: No trust assertions (verified_by, signatures, etc.) - catalog is for discovery only.

func FindComponentByName

func FindComponentByName(c *Catalog, name string) (CatalogComponent, bool)

FindComponentByName finds a tool by exact name match. Note: This only searches the Tools array. For kind-aware lookup, use LookupComponentInCatalog or Catalog.FindByNameAndKind directly. Returns the component and true if found, or zero value and false if not found.

type CatalogMeta

type CatalogMeta = schema.CatalogMeta

CatalogMeta stores metadata about the cached catalog. Stored separately from catalog.json for easy debugging.

func GetCachedMeta

func GetCachedMeta() *CatalogMeta

GetCachedMeta returns the cached meta for use in conditional requests. Returns nil if no meta exists.

func ParseMeta

func ParseMeta(data []byte) (*CatalogMeta, error)

ParseMeta parses meta JSON with strict decoding. Unknown fields cause an error since we control this format.

func ReadMeta

func ReadMeta() (*CatalogMeta, error)

ReadMeta reads the catalog metadata file. Returns ErrNoMeta if no metadata exists.

SECURITY: Uses safefile.ReadFile to refuse symlinks.

type CatalogSource

type CatalogSource = schema.CatalogSource

CatalogSource identifies where the catalog was fetched from.

type ComponentKind

type ComponentKind = componenttypes.ComponentKind

ComponentKind identifies the type of component.

type FetchOptions

type FetchOptions struct {
	// URL to fetch catalog from. If empty, uses DefaultCatalogURL.
	URL string

	// ETag from previous fetch for conditional request.
	ETag string

	// LastModified from previous fetch for conditional request.
	LastModified string

	// HTTPClient to use. If nil, uses default client with timeout.
	HTTPClient *http.Client

	// InsecureAllowHTTP permits HTTP requests to localhost/127.0.0.1 for testing.
	// SECURITY: Only set this in tests. Production code should never set this.
	// CLI: --insecure-allow-http
	InsecureAllowHTTP bool
}

FetchOptions configures the catalog fetch behavior.

type FetchResult

type FetchResult struct {
	Updated    bool       // true if catalog was updated, false if not modified
	Status     MetaStatus // ok, not_modified, or error
	HTTPStatus int        // HTTP status code
	Error      error      // error if Status == error
}

FetchResult contains the outcome of a catalog fetch operation.

func FetchCatalog

func FetchCatalog(ctx context.Context, opts FetchOptions) (*FetchResult, error)

FetchCatalog fetches the catalog from the specified URL using conditional requests. If the catalog hasn't changed (304 Not Modified), returns Updated=false. On success, writes catalog to cache and updates meta.

type LookupResult

type LookupResult struct {
	Name         string   // Component name (e.g., "ai")
	RepoPath     string   // Repository path extracted from RepoURL (e.g., "locktivity/epack-tool-ai")
	Source       string   // Full source string for config (e.g., "locktivity/epack-tool-ai@^1.0")
	Publisher    string   // Publisher name from catalog
	Description  string   // Component description
	Latest       string   // Latest version hint from catalog
	Dependencies []string // Install-time dependencies (component names)
}

LookupResult contains the result of looking up a component in the catalog.

func LookupComponent

func LookupComponent(name string, kind ComponentKind, constraint string) (*LookupResult, error)

LookupComponent finds a component by exact name and kind in the cached catalog and constructs the source string for use in epack.yaml.

The kind parameter specifies which component type to search (tool, collector, etc.). The constraint parameter specifies the version constraint to use in the source string. If constraint is "latest" or empty, only the repo path is used (no @constraint suffix).

Returns ErrNoCatalog if no cached catalog exists. Returns ErrNotFound if the component is not in the catalog.

func LookupComponentInCatalog

func LookupComponentInCatalog(catalog *Catalog, name string, kind ComponentKind, constraint string) (*LookupResult, error)

LookupComponentInCatalog finds a component in the provided catalog. This is useful when you already have the catalog loaded and want to avoid re-reading it.

type MatchType

type MatchType = schema.MatchType

MatchType indicates how the component matched the search query.

type MetaStatus

type MetaStatus = schema.MetaStatus

MetaStatus represents the outcome of the last catalog fetch attempt.

type SearchOptions

type SearchOptions = schema.SearchOptions

SearchOptions configures search behavior.

type SearchResult

type SearchResult = schema.SearchResult

SearchResult represents a component from a search with its match type.

func SearchComponents

func SearchComponents(c *Catalog, query string) []SearchResult

SearchComponents finds components matching the query string. Results are ranked by relevance: exact > prefix > substring. This is a convenience wrapper that avoids callers needing to import the schema package.

Directories

Path Synopsis
Package resolve provides dependency resolution for tool installation.
Package resolve provides dependency resolution for tool installation.
Package schema provides the component catalog schema types and parsing.
Package schema provides the component catalog schema types and parsing.

Jump to

Keyboard shortcuts

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