Documentation
¶
Overview ¶
Package pack provides the build pipeline, SBOM, signing, and secret scanning.
Index ¶
- Constants
- Variables
- func CleanupLocalRegistry(ctx context.Context) error
- func ComputeBuildInputDigest(projectDir string, ignore *IgnoreMatcher) (string, error)
- func CreateBuildContext(projectDir string, ignore *IgnoreMatcher) (io.Reader, error)
- func DefaultAgentPaasIgnore() string
- func DefaultAgentYAML(runtime RuntimeType) string
- func DefaultIgnorePatterns() []string
- func DefaultMainPy() string
- func DeployedAgentPath(homeDir, agentName string) string
- func EnsureLocalRegistry(ctx context.Context) (string, error)
- func GenerateSBOM(ctx context.Context, imageRef string) (sbom []byte, digest string, err error)
- func InitFromCode(projectDir string, runtime RuntimeType) error
- func InitPolicy(projectDir string) error
- func InitScaffold(projectDir string, runtime RuntimeType) error
- func IsDeployed(homeDir, agentName string) bool
- func IsRegistryPortConflict(err error) bool
- func LocalImageRef(agentName, imageDigest string) string
- func PublicKeyFingerprint(pub *ecdsa.PublicKey) string
- func PublicKeyFromPEM(pemBytes []byte) (*ecdsa.PublicKey, error)
- func PushImageToLocalRegistry(ctx context.Context, sourceTag, agentName, agentVersion string) (string, error)
- func RecordDeployment(homeDir, agentName string, lock *AgentLock) error
- func RepairHint(err *OCILayoutError) string
- func ResolveDependencies(ctx context.Context, projectDir string, runtime RuntimeType) ([]string, error)
- func SignImage(ctx context.Context, imageRef string, keyPath string) (referrer string, err error)
- func ValidateOCILayout(layoutPath string) error
- func VerifyAgentLock(lock *AgentLock, imageRef string) error
- func VerifyDeployedIntegrity(homeDir, agentName string, auditAppender audit.AuditAppender) error
- func VerifyLockfileSignature(lock *AgentLock) error
- func WriteAgentLock(lock *AgentLock, path string) error
- type AdvisoryFinding
- type AdvisoryReport
- type AgentLock
- type AgentYAML
- type AuditAppender
- type BuildConfig
- type BuildResult
- type DeployedAgent
- type DetectionResult
- type IgnoreMatcher
- type LLMConfig
- type LockConfig
- type OCILayoutError
- type ReproducibilityMeta
- type RuntimeType
- type ScanConfig
- type ScanResult
- type SecretFinding
Constants ¶
const ( AdvisorySeverityCritical = "CRITICAL" AdvisorySeverityHigh = "HIGH" AdvisorySeverityMedium = "MEDIUM" AdvisorySeverityLow = "LOW" AdvisorySeverityNone = "NONE" )
AdvisorySeverity levels for OSV findings.
const LockSchemaVersion = 1
LockSchemaVersion is the current agent.lock schema version.
Variables ¶
var ErrImmutableViolation = errors.New("immutable violation: deployed agent artifacts cannot be modified in place")
ErrImmutableViolation is returned when an in-place mutation of a deployed agent artifact is attempted.
var ErrOCILayoutCorrupt = errors.New("local OCI layout is missing or corrupt")
ErrOCILayoutCorrupt is returned when the local OCI layout is missing or corrupt.
Functions ¶
func CleanupLocalRegistry ¶
CleanupLocalRegistry stops and removes the agentpaas-registry test container.
func ComputeBuildInputDigest ¶
func ComputeBuildInputDigest(projectDir string, ignore *IgnoreMatcher) (string, error)
ComputeBuildInputDigest computes SHA-256 over the canonical build context. Canonical = sorted file paths (relative to ProjectDir, forward slashes) + each file's content. Respects .agentpaasignore exclusions. Symlink-safe: uses os.Lstat, rejects symlinks.
func CreateBuildContext ¶
func CreateBuildContext(projectDir string, ignore *IgnoreMatcher) (io.Reader, error)
CreateBuildContext creates a deterministic tar reader of the build context. Files are added in sorted path order. Uses ignore matcher to exclude files. Symlink-safe.
func DefaultAgentPaasIgnore ¶
func DefaultAgentPaasIgnore() string
DefaultAgentPaasIgnore returns the default .agentpaasignore content.
func DefaultAgentYAML ¶
func DefaultAgentYAML(runtime RuntimeType) string
DefaultAgentYAML returns the minimal agent.yaml content for scaffolding.
func DefaultIgnorePatterns ¶
func DefaultIgnorePatterns() []string
DefaultIgnorePatterns returns the default exclude patterns used when .agentpaasignore is absent.
func DefaultMainPy ¶
func DefaultMainPy() string
DefaultMainPy returns the default main.py entry point stub.
func DeployedAgentPath ¶
DeployedAgentPath returns the deployed agent state directory.
func EnsureLocalRegistry ¶
EnsureLocalRegistry ensures a local OCI registry is running and returns its URL.
func GenerateSBOM ¶
GenerateSBOM runs syft to produce an SPDX-json SBOM for the built image. Returns the SBOM content and its SHA-256 digest.
func InitFromCode ¶
func InitFromCode(projectDir string, runtime RuntimeType) error
InitFromCode reconciles an agent.yaml from existing source files. If agent.yaml exists, it is left untouched. If not, a minimal one is created with the detected runtime and agent name derived from the dir.
func InitPolicy ¶
InitPolicy writes a minimal default-deny policy.yaml if one does not exist. If policy.yaml already exists, it is left untouched (never overwrite policy).
func InitScaffold ¶
func InitScaffold(projectDir string, runtime RuntimeType) error
InitScaffold creates a new agent project in the given directory. If the directory does not exist, it is created. If agent.yaml already exists, return an error (don't overwrite). Files created:
- agent.yaml (minimal template with name, version, runtime, entry)
- main.py (entry point stub: def app(input): return {"status":"ok"})
- requirements.txt (empty, with a comment)
- .agentpaasignore (default excludes)
func IsDeployed ¶
IsDeployed returns true if the agent has been deployed.
func IsRegistryPortConflict ¶
IsRegistryPortConflict reports whether err indicates the configured registry host port is already bound by a non-agentpaas process.
func LocalImageRef ¶
LocalImageRef returns a digest-pinned image ref for the local registry.
func PublicKeyFingerprint ¶
PublicKeyFingerprint computes the SHA-256 fingerprint of a public key.
func PublicKeyFromPEM ¶
PublicKeyFromPEM parses a PEM-encoded ECDSA P-256 public key.
func PushImageToLocalRegistry ¶
func PushImageToLocalRegistry(ctx context.Context, sourceTag, agentName, agentVersion string) (string, error)
PushImageToLocalRegistry tags and pushes a locally built image to the local registry, returning a digest-pinned image ref suitable for cosign signing.
func RecordDeployment ¶
RecordDeployment writes the deployed agent metadata to disk atomically.
func RepairHint ¶
func RepairHint(err *OCILayoutError) string
RepairHint returns a human-readable repair hint for the given OCILayoutError.
func ResolveDependencies ¶
func ResolveDependencies(ctx context.Context, projectDir string, runtime RuntimeType) ([]string, error)
ResolveDependencies runs uv to lock dependencies. For requirements.txt: `uv pip compile requirements.txt -o /tmp/locked.txt` For pyproject.toml: `uv lock` Returns the list of locked package@version strings. Returns error with verbatim uv output on conflict.
func SignImage ¶
SignImage signs the built image with cosign using the package identity key. Returns the signature referrer path.
func ValidateOCILayout ¶
ValidateOCILayout checks that a local OCI layout directory is valid.
func VerifyAgentLock ¶
VerifyAgentLock verifies an agent.lock manifest.
func VerifyDeployedIntegrity ¶
func VerifyDeployedIntegrity(homeDir, agentName string, auditAppender audit.AuditAppender) error
VerifyDeployedIntegrity checks that the deployed agent.lock and image.digest on disk have NOT been modified since deployment.
func VerifyLockfileSignature ¶
VerifyLockfileSignature verifies the lockfile's ECDSA signature against the AID public key embedded in the lockfile.
func WriteAgentLock ¶
WriteAgentLock writes the agent.lock manifest as canonical JSON to a file.
Types ¶
type AdvisoryFinding ¶
type AdvisoryFinding struct {
ID string `json:"id"`
Package string `json:"package"`
Version string `json:"version"`
Severity string `json:"severity"`
Summary string `json:"summary"`
FixedIn string `json:"fixed_in,omitempty"`
References []string `json:"references,omitempty"`
}
AdvisoryFinding represents a single OSV advisory.
type AdvisoryReport ¶
type AdvisoryReport struct {
Total int `json:"total"`
Critical int `json:"critical"`
High int `json:"high"`
Medium int `json:"medium"`
Low int `json:"low"`
Findings []AdvisoryFinding `json:"findings"`
Scanned bool `json:"scanned"`
RawOutput string `json:"raw_output,omitempty"`
}
AdvisoryReport is the summary of OSV scan results.
func ScanAdvisories ¶
func ScanAdvisories(ctx context.Context, sbomPath string) (*AdvisoryReport, error)
ScanAdvisories runs osv-scanner on the SBOM and returns an advisory summary.
func (*AdvisoryReport) ShouldFailBuild ¶
func (r *AdvisoryReport) ShouldFailBuild(failOnCritical bool) bool
ShouldFailBuild returns true when configured critical/high advisories exist.
func (*AdvisoryReport) Summary ¶
func (r *AdvisoryReport) Summary() string
Summary returns a human-readable summary string for CLI output.
type AgentLock ¶
type AgentLock struct {
// SchemaVersion is the agent.lock schema version (currently 1).
SchemaVersion int `json:"schema_version"`
// AgentName is the agent name from agent.yaml.
AgentName string `json:"agent_name"`
// AgentVersion is the agent version from agent.yaml.
AgentVersion string `json:"agent_version"`
// Runtime is the detected/explicit runtime type (python, langgraph, crewai).
Runtime string `json:"runtime"`
// Platform is the target platform (e.g. "linux/arm64").
Platform string `json:"platform"`
// BaseImageDigest is the digest-pinned distroless base image.
BaseImageDigest string `json:"base_image_digest"`
// HarnessVersion is the version of the harness binary embedded as PID 1.
HarnessVersion string `json:"harness_version"`
// BuildInputDigest is the SHA-256 over the canonical build context.
BuildInputDigest string `json:"build_input_digest"`
// ImageDigest is the SHA-256 digest of the built OCI image.
ImageDigest string `json:"image_digest"`
// SBOMDigest is the SHA-256 digest of the SBOM (SPDX-json).
SBOMDigest string `json:"sbom_digest"`
// PolicyDigest is the SHA-256 digest of the policy.yaml.
// Computed at pack time from the project's policy.yaml.
PolicyDigest string `json:"policy_digest"`
// PackageAID is the Agent Identity Document - the public key PEM.
PackageAID string `json:"package_aid"`
// PublicKeyFingerprint is the SHA-256 fingerprint of the public key.
PublicKeyFingerprint string `json:"public_key_fingerprint"`
// SBOMReferrer is the OCI referrer path for the SBOM artifact.
SBOMReferrer string `json:"sbom_referrer,omitempty"`
// SignatureReferrer is the OCI referrer path for the cosign signature.
SignatureReferrer string `json:"signature_referrer,omitempty"`
// Reproducibility holds build reproducibility metadata.
Reproducibility ReproducibilityMeta `json:"reproducibility"`
// LockfileSignature is the ECDSA signature over the canonical JSON
// of this struct (with LockfileSignature omitted). Base64-encoded.
LockfileSignature string `json:"lockfile_signature"`
// CreatedAt is the wall-clock time the lockfile was created.
// For reproducibility, this is set to SOURCE_DATE_EPOCH, not time.Now().
CreatedAt time.Time `json:"created_at"`
// AgentYAML is the parsed agent.yaml (including LLM config). Stored as part
// of the lockfile for runtime LLM credential resolution. nil when absent.
AgentYAML *AgentYAML `json:"agent_yaml,omitempty"`
}
AgentLock is the canonical, signed manifest for a packed agent. This is the exact review unit consumed by `agentpaas run` and promotion.
func CreateAgentLock ¶
func CreateAgentLock(ctx context.Context, cfg LockConfig) (*AgentLock, error)
CreateAgentLock creates the canonical, signed agent.lock manifest.
func ReadAgentLock ¶
ReadAgentLock reads and parses an agent.lock file.
type AgentYAML ¶
type AgentYAML struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Runtime string `yaml:"runtime"`
Entry string `yaml:"entry"`
Description string `yaml:"description"`
LLM LLMConfig `yaml:"llm"`
Metadata struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Description string `yaml:"description"`
} `yaml:"metadata"`
Spec struct {
Runtime string `yaml:"runtime"`
Entrypoint string `yaml:"entrypoint"`
Entry string `yaml:"entry"`
} `yaml:"spec"`
}
AgentYAML is a minimal subset of agent.yaml fields needed for detection and packaging. The runtime field overrides auto-detection. Both flat fields and the v1 metadata/spec schema are supported.
func LoadAgentYAML ¶
LoadAgentYAML reads and parses agent.yaml from the project directory. Returns nil, nil if agent.yaml does not exist (not an error).
type AuditAppender ¶
type AuditAppender = audit.AuditAppender
AuditAppender is implemented by audit sinks that accept audit records.
type BuildConfig ¶
type BuildConfig struct {
// ProjectDir is the agent project directory to build.
ProjectDir string
// Runtime is the detected/explicit runtime type.
Runtime RuntimeType
// BaseImage is the distroless base image ref (digest-pinned).
// Default: "gcr.io/distroless/python3-debian12@sha256:2fdb05402a2cf21cf78fdb3ba4c5db167241e9e498140f5bf689d7efb773731f"
BaseImage string
// HarnessPath is the path to the pre-built harness binary to embed as PID 1.
// If empty, uses the standard harness binary location.
HarnessPath string
// SourceDateEpoch is the fixed timestamp for reproducible builds.
// Default: time.Unix(0, 0) (epoch).
SourceDateEpoch time.Time
// NonRootUID is the uid for the non-root user. Default: 64000.
NonRootUID int
// ImageTag is the tag for the built image (e.g. "agentpaas/myagent:0.1.0").
ImageTag string
}
BuildConfig controls the image build process.
type BuildResult ¶
type BuildResult struct {
ImageDigest string `json:"image_digest"`
ImageRef string `json:"image_ref"`
BuildTime time.Time `json:"build_time"`
// BuildInputDigest is the SHA-256 over the canonical build context
// (sorted file list + file contents). Same input -> same digest -> same image.
BuildInputDigest string `json:"build_input_digest"`
// DepsLocked is the resolved/locked dependency list from uv.
DepsLocked []string `json:"deps_locked"`
}
BuildResult holds the outcome of an image build.
func BuildImage ¶
func BuildImage(ctx context.Context, cfg BuildConfig) (*BuildResult, error)
BuildImage builds a deterministic OCI image for the agent project.
type DeployedAgent ¶
type DeployedAgent struct {
AgentName string `json:"agent_name"`
ImageDigest string `json:"image_digest"`
SourceDigest string `json:"source_digest"`
LockfileSig string `json:"lockfile_signature"`
DeployedAt time.Time `json:"deployed_at"`
}
DeployedAgent is the metadata of a deployed agent on disk.
func LoadDeployedAgent ¶
func LoadDeployedAgent(homeDir, agentName string) (*DeployedAgent, error)
LoadDeployedAgent reads the deployed agent metadata from disk. Returns os.ErrNotExist if the agent was never deployed.
type DetectionResult ¶
type DetectionResult struct {
Runtime RuntimeType `json:"runtime"`
HasAgentYAML bool `json:"has_agent_yaml"`
ProjectDir string `json:"project_dir"`
ExplicitRuntime bool `json:"explicit_runtime"`
}
DetectionResult holds the outcome of project type detection.
func DetectProject ¶
func DetectProject(projectDir string) (*DetectionResult, error)
DetectProject examines a project directory and returns the runtime type. If agent.yaml exists and has a runtime: field, that overrides detection. Otherwise, scan requirements.txt, pyproject.toml, and .py files for langgraph or crewai imports.
type IgnoreMatcher ¶
type IgnoreMatcher struct {
// contains filtered or unexported fields
}
IgnoreMatcher implements .agentpaasignore pattern matching. It supports:
- Exact filename matches (e.g. ".git")
- Glob patterns (e.g. "*.pyc", "__pycache__")
- Directory patterns (e.g. "node_modules/")
- Comments (lines starting with #)
- Negation patterns (lines starting with !)
func LoadIgnore ¶
func LoadIgnore(projectDir string) (*IgnoreMatcher, error)
LoadIgnore reads .agentpaasignore from projectDir and returns a matcher. If .agentpaasignore does not exist, returns a matcher with default excludes.
func NewIgnoreMatcher ¶
func NewIgnoreMatcher(content string) *IgnoreMatcher
NewIgnoreMatcher creates a matcher from the given .agentpaasignore content.
func (*IgnoreMatcher) Match ¶
func (m *IgnoreMatcher) Match(filePath string) bool
Match returns true if the given path should be ignored (excluded from build context).
type LLMConfig ¶
type LLMConfig struct {
Provider string `yaml:"provider"` // openai|anthropic|xai
Model string `yaml:"model"` // e.g. "gpt-4o", "claude-sonnet-4", "grok-beta"
Credential string `yaml:"credential"` // Keychain secret name (e.g. "openai-key")
}
LLMConfig defines the LLM provider and credential binding for the agent. This is used by the harness to route agent.llm() calls through the gateway as credentialed HTTP egress (Option B unified egress).
type LockConfig ¶
type LockConfig struct {
// BuildResult is the result from BuildImage (T02).
BuildResult *BuildResult
// ScanResult is the result from ScanSecrets (T03).
ScanResult *ScanResult
// AgentYAML is the parsed agent.yaml.
AgentYAML *AgentYAML
// Runtime is the detected runtime type.
Runtime RuntimeType
// BaseImageDigest is the digest-pinned base image.
BaseImageDigest string
// HarnessVersion is the harness binary version.
HarnessVersion string
// Platform is the target platform.
Platform string
// SourceDateEpoch is the fixed timestamp.
SourceDateEpoch time.Time
// KeyStore is the identity keystore for package identity key signing.
KeyStore identityKeyStore
// KeyID is the package identity key ID to use for signing.
KeyID string
// PolicyYAML is the raw policy.yaml file contents. If nil/empty (no policy.yaml
// in the project), the lockfile's PolicyDigest is left empty for backward compat.
PolicyYAML []byte
}
LockConfig controls the agent.lock generation process.
type OCILayoutError ¶
OCILayoutError provides an actionable repair hint when the OCI layout is missing or corrupt.
func (*OCILayoutError) Error ¶
func (e *OCILayoutError) Error() string
func (*OCILayoutError) Is ¶
func (e *OCILayoutError) Is(target error) bool
func (*OCILayoutError) Unwrap ¶
func (e *OCILayoutError) Unwrap() error
type ReproducibilityMeta ¶
type ReproducibilityMeta struct {
// SourceDateEpoch is the fixed timestamp used for the build.
SourceDateEpoch time.Time `json:"source_date_epoch"`
// BaseImagePinned is true if the base image is digest-pinned.
BaseImagePinned bool `json:"base_image_pinned"`
// DepsLocked is true if dependencies were locked via uv.
DepsLocked bool `json:"deps_locked"`
// TarOrder is "sorted" for deterministic tar order.
TarOrder string `json:"tar_order"`
}
ReproducibilityMeta holds metadata for verifying build reproducibility.
type RuntimeType ¶
type RuntimeType string
RuntimeType represents the detected agent runtime/framework.
const ( RuntimePython RuntimeType = "python" RuntimeLangGraph RuntimeType = "langgraph" RuntimeCrewAI RuntimeType = "crewai" RuntimeUnknown RuntimeType = "unknown" )
type ScanConfig ¶
type ScanConfig struct {
// ProjectDir is the agent project directory to scan.
ProjectDir string
// Ignore is the .agentpaasignore matcher (from T01).
Ignore *IgnoreMatcher
// AllowPatterns are regex patterns for secrets that are explicitly allowed.
// Each requires a successful audit append (see AuditAppend below).
AllowPatterns []string
// AuditAppend is called to record an allow-pattern justification.
// If nil, --allow-secret-pattern aborts with an error.
AuditAppend AuditAppender
}
ScanConfig controls the secret scan process.
type ScanResult ¶
type ScanResult struct {
// Findings from source tree scan.
SourceFindings []SecretFinding `json:"source_findings"`
// Findings from build context scan (after .agentpaasignore applied).
ContextFindings []SecretFinding `json:"context_findings"`
// ContextSize is the total build context size in bytes.
ContextSize int64 `json:"context_size"`
// ContextSizeWarning is true if ContextSize > 100MB.
ContextSizeWarning bool `json:"context_size_warning"`
}
ScanResult holds the outcome of a secret scan.
func ScanSecrets ¶
func ScanSecrets(ctx context.Context, cfg ScanConfig) (*ScanResult, error)
ScanSecrets runs gitleaks over the source tree and effective build context. Steps: 1. Run gitleaks on the full source tree (no ignore filtering). 2. Run gitleaks on the effective build context (after .agentpaasignore). 3. Compute build context size (sum of non-ignored file sizes). 4. Warn if context >100MB. 5. Apply allow-patterns (with audit append requirement). Returns ScanResult with findings. Does NOT fail itself — caller checks findings.
func (*ScanResult) FailClosed ¶
func (r *ScanResult) FailClosed() bool
FailClosed returns true if the scan should fail (secrets found that are not allow-patterned with audit append).
func (*ScanResult) HasSecrets ¶
func (r *ScanResult) HasSecrets() bool
HasSecrets returns true if any findings exist (source or context).
type SecretFinding ¶
type SecretFinding struct {
// File is the relative path from ProjectDir.
File string `json:"file"`
// Line is the 1-based line number.
Line int `json:"line"`
// Rule is the gitleaks rule ID that matched.
Rule string `json:"rule"`
// Secret is the masked secret value (first 4 chars + *** + last 4 chars).
Secret string `json:"secret"`
// contains filtered or unexported fields
}
SecretFinding represents a detected secret in the source or build context.