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 ¶
BuiltinPack returns the embedded pack with the given name, or an error if no such built-in exists.
func BuiltinPacks ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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
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
LoadPackLock reads the project's pack lockfile, returning an empty lock when none exists yet.
func (*PackLock) CheckAndPin ¶ added in v0.2.0
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.
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.