pack

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package pack implements specd's declarative scaffold packs: named bundles of files (with template variables) that `specd init`/`new` can apply to seed a spec directory. Pack manifests are pure data — parsing explicitly rejects any hook/exec/command/script field and any file path that could escape the project root — so applying a pack can only ever write files, never run code. Built-in packs are embedded at build time via go:embed and validated through the same ParsePack path as user-supplied manifests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ResolveFromRegistry added in v0.2.0

func ResolveFromRegistry(name, registryURL string) (*Pack, RegistryEntry, error)

ResolveFromRegistry clones the registry git repo, looks up name, and resolves the referenced pack with fail-closed SHA256 verification. It returns the parsed pack and the resolved entry (whose SHA256 the caller pins into the lockfile).

Types

type Pack

type Pack struct {
	Name        string            `json:"name"`
	Version     string            `json:"version"`
	Description string            `json:"description"`
	Files       []PackFile        `json:"files"`
	Vars        map[string]string `json:"vars,omitempty"`
}

Pack is a declarative spec-scaffold bundle. The manifest is pure data: a set of files to write plus template variables. It is intentionally NOT executable — there is no hook, command, or script field — so resolving and applying a pack carries no code-execution surface.

func BuiltinPack

func BuiltinPack(name string) (*Pack, error)

BuiltinPack returns the embedded pack with the given name, or an error if no such built-in exists.

func BuiltinPacks

func BuiltinPacks() ([]*Pack, error)

BuiltinPacks returns the embedded built-in packs, sorted by name. A malformed embedded pack is a build/test failure surfaced here, not a silent skip.

func ParsePack

func ParsePack(raw []byte) (*Pack, error)

ParsePack decodes and validates a pack manifest. It fails closed: unknown fields (including any executable-hook key), unsafe file paths, and missing required fields are all rejected with no partial Pack returned.

func ResolvePack

func ResolvePack(ref, sha256Pin string) (*Pack, error)

ResolvePack resolves a pack reference to a validated Pack. A bare name (no scheme) resolves against the embedded built-in packs. An http(s) URL is a remote pack and MUST carry a pinned sha256 digest: the bytes are downloaded, hashed, and compared before parsing — on any mismatch nothing is returned (fail-closed), mirroring `specd update`'s SHA256SUMS contract. Either way the manifest passes ParsePack, so a resolved pack is always declarative-only and path-safe.

func VerifyAndParsePack

func VerifyAndParsePack(raw []byte, sha256Pin, source string) (*Pack, error)

VerifyAndParsePack checks raw bytes against a pinned SHA256 digest and, only on an exact match, parses them as a pack manifest. A digest mismatch returns an error and no pack — the caller must write nothing. Exposed for direct testing of the fail-closed contract without a network round-trip.

type PackApplyResult

type PackApplyResult struct {
	Pack    string
	Written []string
	Skipped []string
}

PackApplyResult reports what an ApplyPack call did. Written lists the repo-relative paths created; Skipped lists declared files that already existed (only populated when force is false).

func ApplyPack

func ApplyPack(root string, p *Pack, force bool) (PackApplyResult, error)

ApplyPack writes a resolved pack's files under root. It is transactional: it pre-checks the whole plan (paths are re-validated, collisions detected) before writing anything, and if any write fails it removes every file it created in this call — so a failed apply never leaves a partial scaffold. Without force, a pre-existing target is a hard error (fail-closed) rather than an overwrite, keeping the apply all-or-nothing. Vars are substituted into file content.

type PackFile

type PackFile struct {
	Path    string `json:"path"`
	Content string `json:"content"`
}

PackFile is one scaffold file a pack writes, relative to the project root. Content is inline and declarative — packs never reference scripts, commands, or hooks (see ParsePack), so applying a pack can only ever write files.

type PackLock added in v0.2.0

type PackLock struct {
	Packs map[string]string `json:"packs"`
}

PackLock is the checksum lockfile: a name→sha256 map recording every pack a project has resolved. It is the pin that turns a mutated registry into a hard failure rather than a silent swap.

func LoadPackLock added in v0.2.0

func LoadPackLock(root string) (PackLock, error)

LoadPackLock reads the project's pack lockfile, returning an empty lock when none exists yet.

func (*PackLock) CheckAndPin added in v0.2.0

func (l *PackLock) CheckAndPin(name, sha256 string) error

CheckAndPin verifies name against any previously locked digest and records the new one. A disagreement is a hard failure (the registry changed a pack's bytes under a stable name); a first sighting is pinned.

func (PackLock) Save added in v0.2.0

func (l PackLock) Save(root string) error

Save writes the lockfile deterministically (sorted keys via json map ordering).

type RegistryEntry added in v0.2.0

type RegistryEntry struct {
	Name   string `json:"name"`
	URL    string `json:"url"`
	SHA256 string `json:"sha256"`
}

RegistryEntry is one pack's pinned coordinates in the registry index.

type RegistryIndex added in v0.2.0

type RegistryIndex struct {
	Packs []RegistryEntry `json:"packs"`
}

RegistryIndex is the parsed registry.json carried by the registry git repo.

func ParseRegistryIndex added in v0.2.0

func ParseRegistryIndex(raw []byte) (RegistryIndex, error)

ParseRegistryIndex decodes and validates a registry index. It fails closed on unknown fields, empty names/URLs, malformed digests, and duplicate names.

func (RegistryIndex) LookupRegistryEntry added in v0.2.0

func (idx RegistryIndex) LookupRegistryEntry(name string) (RegistryEntry, error)

LookupRegistryEntry finds a pack by name in the index.

Jump to

Keyboard shortcuts

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