artifact

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 36 Imported by: 0

Documentation

Overview

Package artifact is OCI artifact distribution (ADR-0031): how a function source bundle reaches the platform. funcdctl pushes a bundle as an OCI artifact to a target (a local OCI layout for dev, or a registry for prod) and the platform pulls it by digest. It provides the producer side (Push/Pull/Login/Logout) and the consumer side — an OrasMaterializer that is a driver of ADR-0030's internal/function.Materializer seam.

The artifact is one digest-addressed OCI artifact: a manifest of artifactType application/vnd.funcd.function.artifact.v1 with a single bundle-blob layer. The imageDigest is the manifest descriptor digest and is the authority — pulls are by digest, an empty digest is rejected, and a mutable tag is only a locator.

bundle.go — the multi-file function bundle (ADR-0089): a deployment-package artifact.

A bundle is a directory (handler + vendored native deps + the ADR-0090 I/O contract) pushed as ONE deterministic tar+gzip OCI layer alongside the ADR-0031 single-blob layer (additive — a lone .py/.mjs push is unchanged). The transport machinery here is language-agnostic; only the PYTHONPATH worker env (internal/function) is python-family-gated. The tar is deterministic (entries sorted; mtime/uid/gid/uname/gname zeroed) so identical trees yield an identical digest (ADR-0035 pinning holds), and untar is traversal-safe (a "../"/absolute/symlink-escape path is refused — a security gate).

site.go — the static-site bundle artifact (ADR-0139, F103): a prebuilt web app pushed as ONE deterministic tar+gzip layer (the ADR-0089 transport, reused) under its own artifact type. A site has no I/O contract and no runtime, so the manifest carries no contract blob and no runtime annotation; the distinct type keeps a site from ever being pulled as a function artifact.

Index

Constants

View Source
const (
	// BundleTarMediaType is the multi-file function bundle layer (ADR-0089): a deterministic
	// tar+gzip deployment package (handler + vendored deps). It sits ALONGSIDE the single-file
	// bundleMediaType layer (ADR-0031) — additive, never replacing it.
	BundleTarMediaType = "application/vnd.funcd.bundle.tar+gzip"
	// BundleEntryAnnotation records the handler entry file, relative to the bundle root, on the
	// bundle layer + manifest so Pull/Materialize resolve FUNCD_ARTIFACT to <root>/<entry>.
	BundleEntryAnnotation = "dev.funcd.bundle.entry"
)
View Source
const PlatformAnnotation = "dev.funcd.platform"

PlatformAnnotation records, on a function manifest, the platform its bundle was built for (ADR-0145).

View Source
const SiteArtifactType = "application/vnd.funcd.site.artifact.v1"

SiteArtifactType marks an OCI manifest as a funcd static-site bundle: one BundleTarMediaType layer, no contract blob and no runtime annotation (a site has no I/O contract). A distinct type keeps a site from being pulled by the function materializer.

View Source
const VoidSchema = `{"type":"null"}`

VoidSchema is the canonical void side (ADR-0090): a side that carries no meaningful payload is the explicit JSON Schema {"type":"null"} — never an omission. Both sides are always present in the blob; a void side declares itself with this schema, and its validator is compiled from it like any other.

Variables

This section is empty.

Functions

func ContractBlob

func ContractBlob(input, output []byte) ([]byte, error)

ContractBlob assembles the mandatory {dialect, input, output} contract blob (ADR-0090, supersedes ADR-0059's optional form). BOTH input and output must be present and non-empty — a void side is VoidSchema, never nil. Returns fault.Invalid if either is missing; there is no contract-less artifact. The marshaled JSON always serializes both fields (no omitempty).

func Inspect

func Inspect(ctx context.Context, ref, digest string) (contract []byte, err error)

Inspect reads a function's I/O contract straight from its OCI manifest (ADR-0059): it fetches the manifest + the small contract blob ONLY — never the bundle layer, never executing code — and returns the raw contract JSON ({input?, output?, dialect}). It resolves by digest when one is supplied (tamper-evident: the inspected contract == the deployed one); a bare tag is resolved to its current manifest. fault.NotFound when the artifact carries no contract.

func InspectContract

func InspectContract(ctx context.Context, ref, digest string) (contract []byte, resolvedDigest string, err error)

InspectContract is Inspect that also returns the resolved manifest descriptor digest (ADR-0098): the single metadata fetch already yields it, so a caller (the workflow contract-check gate) can record the pinned ref@digest alongside the contract without a second round-trip. Same static-inspection invariant — the bundle bytes are never fetched.

func InspectRuntime

func InspectRuntime(ctx context.Context, ref, digest string) (runtime string, err error)

InspectRuntime reads a function's runtime class straight from its OCI manifest annotation (dev.funcd.runtime.v1, ADR-0094): it fetches the manifest ONLY — never the bundle, never the contract, never executing code — so the workflow materializer can resolve a step image's runtime without pulling it. It resolves by digest when supplied (tamper-evident), else a bare tag. fault.NotFound when the artifact asserts no runtime.

func IsArtifactPlatform added in v0.2.0

func IsArtifactPlatform(p v1.OCIPlatform) bool

IsArtifactPlatform reports whether `funcdctl push --platform` accepts p.

func IsDigest added in v0.2.2

func IsDigest(reference string) bool

IsDigest reports whether a ref's reference part is a digest rather than a tag.

func Login

func Login(ctx context.Context, registry, user, pass string) error

Login stores registry credentials via oras-go's credential store (the local OCI layout needs no login). It verifies the credential against the registry.

func Logout

func Logout(ctx context.Context, registry string) error

Logout removes stored credentials for a registry.

func PackBundle

func PackBundle(dir, entry string) (data []byte, err error)

PackBundle writes dir as a DETERMINISTIC tar+gzip stream: entries are sorted by path and mtime/uid/gid/uname/gname are zeroed, so two identical trees produce byte-identical output (and thus an identical digest — ADR-0035). Only regular files and directories are packed: any other entry (a symlink, a device) is fault.Invalid, never silently left out. entry must name an existing regular file relative to dir (the handler) — else fault.Invalid.

func Platforms added in v0.2.0

func Platforms(ctx context.Context, ref, digest string) ([]v1.OCIPlatform, error)

Platforms lists the platforms the artifact at digest (or at ref's tag when digest is empty) provides: an index's, an annotated manifest's one, or nil for an unannotated manifest, which runs anywhere. An index none of whose manifests names a platform runs nowhere: an error matching scheduler.ErrNoMatchingPlatform.

func Pull

func Pull(ctx context.Context, ref, digest, dir string, node v1.OCIPlatform) (path string, err error)

Pull fetches the artifact named by ref, verifies it against digest (the authority — empty digest is rejected), and writes the bundle blob into dir, returning its path. When digest names an OCI image index (ADR-0145), the manifest for node ("" ⇒ the daemon's own platform) is used.

func PullSite

func PullSite(ctx context.Context, ref, digest, dir string) error

PullSite fetches the digest-pinned site artifact and untars its bundle layer into dir using the existing traversal-safe untar (a "../"/absolute/symlink-escape entry is refused). The manifest is fetched BY DIGEST so a moved tag can never change what materializes.

func Push

func Push(ctx context.Context, ref, file string, contract []byte, runtime string, platform v1.OCIPlatform) (digest string, err error)

Push packages file as the §1 OCI artifact and pushes it to ref's target (a local OCI layout or a registry), returning the manifest descriptor digest. A light pre-flight rejects an empty bundle and a dotfile name (Pull refuses it as a title); the authoritative shape-gate is the shim (ADR-0030). When contract is non-nil (ADR-0059), it adds a content-addressed contract blob layer + the dev.funcd.contract.v1 manifest annotation; nil ⇒ the unchanged ADR-0031 artifact. A non-empty platform records PlatformAnnotation (ADR-0145); "" records none.

func PushBundle

func PushBundle(ctx context.Context, ref, dir, entry, runtime string, platform v1.OCIPlatform) (digest string, err error)

PushBundle packs dir (PackBundle) as a BundleTarMediaType layer with the entry annotation, adds the VerifyBundleContract result as the ADR-0059 contract layer, and pushes it — mirroring Push's oras flow. Returns the manifest descriptor digest.

func PushIndex added in v0.2.0

func PushIndex(ctx context.Context, ref string, sources []string) (digest string, err error)

PushIndex writes an OCI image index over sources — per-platform function manifests in the same repository or layout as ref — tags it from ref and returns its digest (ADR-0145 Decision 2). Every rule is checked before anything is written; a violation is fault.Invalid naming the source. The sources are read without opening the target for writing, so a ref to a directory that holds no layout is fault.NotFound and writes nothing (issue #451).

func PushSite

func PushSite(ctx context.Context, ref, dir string) (digest string, err error)

PushSite packs dir as the deterministic tar+gzip bundle layer (ADR-0089) under SiteArtifactType and pushes it to ref's target, returning the manifest digest. Empty dir ⇒ fault.Invalid. It packs WITHOUT an entry-file gate (a site's index is a reconcile-time spec.index, unknown at push).

func ResolveSite

func ResolveSite(ctx context.Context, ref string) (digest string, err error)

ResolveSite resolves ref (a tag or a digest) to its manifest digest, asserting SiteArtifactType. A function artifact ⇒ fault.Invalid; an absent ref ⇒ fault.NotFound.

func VerifyBundleContract

func VerifyBundleContract(dir, _ string) (contractBlob []byte, err error)

VerifyBundleContract enforces the push-time bundle-contract gate (ADR-0089 §3 / ADR-0090 / ADR-0123): dir/__funcd_contract.json MUST exist and be a valid {input, output} document with BOTH keys present (a void side is {"type":"null"}, never absent) AND each side must lie within the funcd type profile (contract.Check — the same gate the single-file --schema path applies). It no longer requires a baked validator symbol in the entry file: the artifact is schema-only and the runtime shim compiles the validator from the delivered schema at worker warm-up (ADR-0123, supersedes ADR-0060's build-time bake). The `entry` argument is retained for the signature but is no longer read. It returns the {dialect, input, output} blob to promote through the EXISTING ContractBlob path. fault.Invalid on any gap — an out-of-profile schema that slipped through here would otherwise only fail at worker compile-time (cold-start fail-closed).

Types

type OrasMaterializer

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

OrasMaterializer is a DRIVER of ADR-0030's internal/function.Materializer: it pulls a Function's artifact by digest into a per-digest cache dir (immutable) and returns the local path the shim reads. The local-file driver (ADR-0030) stays the no-dep test stand-in.

func NewOrasMaterializer

func NewOrasMaterializer(artifactDir string, node v1.OCIPlatform) *OrasMaterializer

NewOrasMaterializer builds the OCI-backed Materializer caching under artifactDir, for a node running node ("" ⇒ the daemon's own platform).

func (*OrasMaterializer) Materialize

func (m *OrasMaterializer) Materialize(ctx context.Context, fn *v1.Function) (string, error)

Materialize resolves fn.spec.image → target, pulls by fn.spec.imageDigest (the authority; empty → fault.Invalid), and returns the cached local path.

func (*OrasMaterializer) Platforms added in v0.2.0

func (m *OrasMaterializer) Platforms(ctx context.Context, uri, digest string) ([]v1.OCIPlatform, error)

Platforms implements function.PlatformResolver (ADR-0145): the platforms the artifact at digest provides, cached per digest in memory and in the artifact cache dir, so a restarted daemon starts a cached artifact without its source.

func (*OrasMaterializer) Resolve

func (m *OrasMaterializer) Resolve(ctx context.Context, uri string) (string, error)

Resolve resolves an OCI artifact ref (its tag) to the manifest digest (ADR-0035), so the reconciler can pin it into the immutable Revision without the user typing it. It is the ArtifactResolver seam the Function reconciler calls at Revision-stamp time.

Jump to

Keyboard shortcuts

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