platform

package
v0.1.0-dev.20260903040058 Latest Latest
Warning

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

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

Documentation

Overview

Package platform models a target platform as a standalone, op-free capability.

A platform is its OS, architecture, distro, and the package and service managers available on it. It is constructed by cloning a named default Spec (e.g. Debian, Fedora, Darwin, Windows) or by detecting the host (Detect), optionally mutating the spec via its `With*` methods, then sealing it with New. The sealed Platform exposes its identity plus one PackageManager — the Composite router over the platform's leaf drivers — and one ServiceManager. `pkg/platform` imports nothing from `pkg/op`; `pkg/op` imports it (the same shape as `pkg/result` and `pkg/status`).

Build tags apply only to the per-OS manager primitives (`*_<os>.go`) and host detection (`detect_<os>.go`). The manager types and the contract compile on every host, so a graph can target any platform from any host; the run-time preflight catches target-vs-host mismatches before a wrong-platform manager is invoked.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DetectToken

func DetectToken() string

DetectToken detects the host platform and returns its canonical token, falling back to "Linux" when detection fails.

Returns:

  • `string`: the host's canonical token, or "Linux" when the host cannot be detected.

func Token

func Token(p Platform) string

Token returns the canonical dotted platform token: "Darwin", "Windows", "Linux.Debian", "Linux.Fedora", or "Linux" when the distro family is unknown.

The token is the vocabulary the devlore tools share — lore's registry resolves platform-partitioned script directories by it (`docker/Linux.Debian/Deploy/`), writ's tree matches segment-variant directories with the same capitalized names, and manifest planning selects releases by it. Distro grouping is by package-manager family: apt-based distributions render as `Linux.Debian`, dnf/yum-based as `Linux.Fedora`.

Parameters:

  • `p`: the platform to render.

Returns:

  • `string`: the canonical token.

Types

type PURL

type PURL struct {
	Type       string            // package ecosystem ("brew", "deb", "winget", etc.)
	Namespace  string            // owner/group prefix (winget publisher, npm scope, Maven group ID)
	Name       string            // the package name
	Version    string            // release version
	Qualifiers map[string]string // key=value pairs (OS, arch, repository, distro)
	Subpath    string            // path within the package
}

PURL is a structured Package URL (purl) identity, modeled after url.URL.

The purl specification defines the canonical format:

pkg:{type}/{namespace}/{name}@{version}?{qualifiers}#{subpath}

Type and Name are required. All other components are optional.

func ParsePURL

func ParsePURL(raw string) (*PURL, error)

ParsePURL parses a purl string into its components.

Parameters:

  • raw: the purl string (e.g., "pkg:brew/jq@1.7").

Returns:

  • *PURL: the parsed components, or nil on error.
  • error: non-nil if the string is not a valid purl.

func (PURL) String

func (p PURL) String() string

String returns the canonical purl string representation.

Returns:

  • string: the purl URI (e.g., "pkg:brew/jq@1.7").

type PackageManager

type PackageManager interface {

	// Install converges each package to present at the requested version.
	//
	// Parameters:
	//   - `packages`: the packages to install, each carrying its resolved [PURL].
	//   - `kwargs`: opaque native-installer flags passed through verbatim per manager (e.g. `cask`).
	//
	// Returns:
	//   - `receipts`: one [Receipt] per package, in input order; a receipt's `Err` is set from the observed
	//     post-state, not the command's exit code.
	//   - `err`: non-nil when any receipt failed.
	Install(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)

	// Remove converges each package to absent.
	//
	// Parameters:
	//   - `packages`: the packages to remove, each carrying its resolved [PURL].
	//   - `kwargs`: opaque native-installer flags passed through verbatim per manager.
	//
	// Returns:
	//   - `receipts`: one [Receipt] per package, in input order.
	//   - `err`: non-nil when any receipt failed.
	Remove(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)

	// Upgrade moves each named package to the latest available version.
	//
	// Parameters:
	//   - `packages`: the packages to upgrade, each carrying its resolved [PURL].
	//   - `kwargs`: opaque native-installer flags passed through verbatim per manager.
	//
	// Returns:
	//   - `receipts`: one [Receipt] per package, in input order.
	//   - `err`: non-nil when any receipt failed.
	Upgrade(packages []PURL, kwargs map[string]any) (receipts []Receipt, err error)

	// Update forces an immediate index refresh, bypassing the automatic staleness gate.
	//
	// On a leaf it refreshes that leaf's index now — a no-op for a manager with no local index (a live-store
	// manager such as snap / flatpak / winget). On the router it fans out to every leaf.
	//
	// Returns:
	//   - `error`: aggregated per-leaf refresh failures; nil when every refresh succeeded or had nothing to do.
	Update() error

	// Installed reports whether the package identified by `p` is installed.
	//
	// Parameters:
	//   - `p`: the package [PURL] to query.
	//
	// Returns:
	//   - `bool`: true when the package is installed.
	Installed(p PURL) bool

	// Version returns the installed version of the package identified by `p`, or empty when it is not installed.
	//
	// Parameters:
	//   - `p`: the package [PURL] to query.
	//
	// Returns:
	//   - `string`: the installed version, or "" when absent.
	Version(p PURL) string

	// Available reports whether the package identified by `p` exists in the manager's index.
	//
	// Parameters:
	//   - `p`: the package [PURL] to query.
	//
	// Returns:
	//   - `bool`: true when the package is available to install.
	Available(p PURL) bool

	// Search returns up to `limit` packages whose name or description matches `query`.
	//
	// Parameters:
	//   - `query`: the search term.
	//   - `limit`: the maximum number of results; `limit` <= 0 means no limit.
	//
	// Returns:
	//   - `[]SearchResult`: the matches, each tagged with the `Manager` that produced it; nil when none match.
	Search(query string, limit int) []SearchResult

	// Present reports whether the manager's executable is on the PATH.
	//
	// Alone among the queries this asks about the manager, not a package: it is a per-machine fact, so it
	// neither varies by [PURL] nor consults an index. A [Spec] declares its managers from the detected OS and
	// distro — "Debian-family, therefore apt" — which is a statement about the platform, not about this
	// machine. Present is what closes that gap, and it does so with a PATH lookup: no subprocess, no network.
	//
	// It answers whether the tool is there, not whether an operation through it will succeed. A present
	// manager can still fail to install — a lock, a bad mirror, no privilege — and that failure belongs to
	// the operation that hits it, reported where it happens.
	//
	// Returns:
	//   - `bool`: true when the executable resolves on the PATH.
	Present() bool
}

PackageManager is the Composite package-management contract.

The same surface serves a single leaf driver and the platform's router over many leaves. Routing is by purl: every package reaching a manager is a PURL whose `Type` selects the leaf (the router dispatches; a leaf ignores routing and acts on whatever slice it is handed). The mutating triad — Install / Remove / Upgrade — is best-effort across its slice and returns one Receipt per package; partial failure is normal. Index refresh is automatic and staleness-gated per leaf before index-consuming operations; PackageManager.Update is the manual force-refresh override (the router fans it out to every leaf). The query methods report a single package's observed state and back the veneer's predicates (Installed / Version / Available) and federated search.

type Platform

type Platform interface {

	// OS returns the operating system family ("linux", "darwin", "windows").
	OS() string

	// Arch returns the architecture ("amd64", "arm64", "arm/v7", etc.) per Docker's vocabulary.
	Arch() string

	// Distro returns the distribution identifier ("ubuntu", "fedora", "macos", "windows", etc.).
	Distro() string

	// Version returns the OS or distro version string ("22.04", "14.5", "11", etc.). Empty when unknown.
	Version() string

	// Hostname returns the host's network hostname. Empty when unavailable.
	Hostname() string

	// DefaultConcurrency returns a reasonable concurrency level for parallel operations — typically 4 × NumCPU.
	DefaultConcurrency() int

	// DefaultPurlType returns the purl type of the platform's default native manager (e.g. "deb" on Debian).
	//
	// The veneer uses it to normalize a bare package name into a typed purl.
	DefaultPurlType() string

	// ResolvePurlType maps a caller-supplied manager prefix — a manager name or a purl type — to the canonical
	// purl type, reporting whether the prefix names a known manager on this platform.
	ResolvePurlType(prefix string) (string, bool)

	// PackageManager returns the platform's Composite router over its leaf drivers.
	PackageManager() PackageManager

	// ServiceManager returns the service manager for this platform (systemd, launchd, Service Control Manager).
	ServiceManager() ServiceManager
}

Platform exposes a target's classification and the package and service managers available on it.

Implementations are immutable; construct via New. Callers receive a Platform from the runtime environment and never construct it directly outside of a named Spec factory + New or Detect + New.

func New

func New(spec *Spec) (Platform, error)

New validates `spec` and returns the immutable Platform it describes.

Validation:

  • OS must be set and one of "linux", "darwin", "windows".
  • Arch must be in [knownArches]; empty defaults to `runtime.GOARCH` (which must itself be a known arch).
  • For OS=="linux", Distro must be in [knownLinuxDistros]; for "darwin" it must be "macos"; for "windows", "windows".

Parameters:

  • `spec`: the populated *Spec (from a named factory or Detect, optionally mutated via `With*`).

Returns:

  • `Platform`: the sealed platform value.
  • `error`: a single descriptive error per failing validation.

type Receipt

type Receipt struct {

	// Purl is the package the operation acted on; its `Type` identifies the leaf that handled it.
	Purl PURL

	// PriorVersion is the installed version observed before the operation, or "" when the package was absent.
	PriorVersion string

	// Version is the installed version observed after the operation, or "" when the package is absent (removed).
	Version string

	// Err is non-nil when the observed post-state did not reach what the package's [PURL] requested.
	Err error
}

Receipt records the outcome of one package operation.

State is observed by re-query, never by screen-scraping command output: a leaf pre-queries the installed version, runs the (idempotent) command, then re-queries — `PriorVersion` and `Version` are those two observations, and `Err` is set when the post-state did not reach what the package's PURL requested. One Receipt is produced per package; the Composite router concatenates the leaves' receipts into one unified result.

type Result

type Result struct {
	OK     bool   // whether the command exited zero
	Stdout string // captured standard output, trailing newline trimmed
	Stderr string // captured standard error, trailing newline trimmed
	Code   int    // the process exit code (-1 when the command could not be launched)
}

Result represents a command-execution result.

It is returned by a leaf's raw shell-out primitives and by ServiceManager mutators.

type SearchResult

type SearchResult struct {
	Name        string // the package name
	Version     string // the available version, when the manager reports one
	Description string // a short description, when the manager reports one
	Manager     string // the purl type of the leaf that produced the hit (e.g. "deb", "brew")
}

SearchResult represents a package found by PackageManager.Search.

Manager records the leaf that produced the hit (the purl type, e.g. "deb", "brew"), so a federated search across the router's leaves yields results that self-identify their source.

type ServiceManager

type ServiceManager interface {

	// Exists reports whether a service with the given name is registered.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `bool`: true when the service exists.
	Exists(name string) bool

	// IsRunning reports whether the named service is currently running.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `bool`: true when the service is running.
	IsRunning(name string) bool

	// IsEnabled reports whether the named service is enabled to start at boot.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `bool`: true when the service is enabled.
	IsEnabled(name string) bool

	// Status returns a coarse, human-facing status for the named service.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `string`: the status (e.g. "running", "stopped").
	Status(name string) string

	// Start starts the named service.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `Result`: the command result.
	Start(name string) Result

	// Stop stops the named service.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `Result`: the command result.
	Stop(name string) Result

	// Enable enables the named service to start at boot.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `Result`: the command result.
	Enable(name string) Result

	// Disable disables the named service from starting at boot.
	//
	// Parameters:
	//   - `name`: the service name.
	//
	// Returns:
	//   - `Result`: the command result.
	Disable(name string) Result

	// NeedsSudo reports whether mutating service operations require elevation.
	//
	// Returns:
	//   - `bool`: true when elevation is required.
	NeedsSudo() bool
}

ServiceManager abstracts service-management operations.

Concrete implementations exist for systemd (Linux), launchd (Darwin), and Service Control Manager (Windows).

type Spec

type Spec struct {
	// contains filtered or unexported fields
}

Spec is the mutable builder for a Platform.

Obtain one by cloning a named default (Debian, Fedora, Darwin, Windows, …) or via Detect, chain `With*` to override defaults, then pass it to New. Specs are mutable during the chain (each `With*` mutates the receiver and returns it). The caller should not retain the spec after New; the returned Platform is the durable value. The manager fields are populated by the named factories and are not part of the public `With*` surface.

func AlmaLinux

func AlmaLinux() *Spec

AlmaLinux returns a fresh *Spec for AlmaLinux (dnf default; dnf + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func CentOSStream

func CentOSStream() *Spec

CentOSStream returns a fresh *Spec for CentOS Stream (dnf default; dnf + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Darwin

func Darwin() *Spec

Darwin returns a fresh *Spec for macOS (brew default; brew + port available; launchd services).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Debian

func Debian() *Spec

Debian returns a fresh *Spec for Debian (apt default; apt available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Detect

func Detect() (*Spec, error)

Detect inspects the running host and returns a fresh, mutable *Spec reflecting it.

The spec reflects the host's actual OS, distro, architecture, version, hostname, and managers; seal it into a Platform with New. Detect is the only host-inspecting entry point; the named factories (Debian, Fedora, Darwin, Windows, …) are deterministic and touch nothing on the host. On Linux, Detect reads /etc/os-release for the distro and refines the available-manager set per the running variant (stripping desktop-only managers like flatpak on server installs). On Darwin it runs `sw_vers`; on Windows, `cmd /c ver`.

Returns:

  • `*Spec`: the detected host spec.
  • `error`: when the host OS is not one of linux / darwin / windows, or when detection fails.

func Fedora

func Fedora() *Spec

Fedora returns a fresh *Spec for Fedora (dnf default; dnf + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Mint

func Mint() *Spec

Mint returns a fresh *Spec for Linux Mint (apt default; apt + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func RHEL

func RHEL() *Spec

RHEL returns a fresh *Spec for Red Hat Enterprise Linux (dnf default; dnf + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Rocky

func Rocky() *Spec

Rocky returns a fresh *Spec for Rocky Linux (dnf default; dnf + flatpak available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Ubuntu

func Ubuntu() *Spec

Ubuntu returns a fresh *Spec for Ubuntu (apt default; apt + snap available).

Returns:

  • `*Spec`: the fresh, mutable spec.

func Windows

func Windows() *Spec

Windows returns a fresh *Spec for Windows (winget default and only; Service Control Manager services).

Returns:

  • `*Spec`: the fresh, mutable spec.

func (*Spec) WithArch

func (s *Spec) WithArch(arch string) *Spec

WithArch sets the architecture. Empty defaults to `runtime.GOARCH` at New time.

Parameters:

  • `arch`: a [knownArches] value, or "" for the host arch.

Returns:

  • `*Spec`: the receiver, for chaining.

func (*Spec) WithDefaultConcurrency

func (s *Spec) WithDefaultConcurrency(n int) *Spec

WithDefaultConcurrency sets the suggested concurrency level for parallel operations.

Parameters:

  • `n`: the concurrency level.

Returns:

  • `*Spec`: the receiver, for chaining.

func (*Spec) WithHostname

func (s *Spec) WithHostname(hostname string) *Spec

WithHostname sets the host's network hostname.

Parameters:

  • `hostname`: the hostname.

Returns:

  • `*Spec`: the receiver, for chaining.

func (*Spec) WithVersion

func (s *Spec) WithVersion(version string) *Spec

WithVersion sets the OS or distro version string ("22.04", "14.5", etc.).

Parameters:

  • `version`: the version string.

Returns:

  • `*Spec`: the receiver, for chaining.

Jump to

Keyboard shortcuts

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