Documentation
¶
Overview ¶
Package sdk is the typed Go client over the funcd control-plane REST API (ADR-0024). It speaks the code-first huma surface (ADR-0005/0018) at /apis/funcd.io/v1alpha1/..., exposing a kind-parameterized CRUD surface (Apply/Get/List/Delete) typed via the v1.Object interface — no generics, no `any`. It is on the public surface and depends only on api/** + stdlib.
Index ¶
- Constants
- func DecodeManifest(data []byte) (v1.Object, error)
- func DecodeManifests(data []byte) ([]v1.Object, error)
- func GenerateTypes(m *Manifest) (map[string][]byte, error)
- func KindFromToken(token string) (v1.Kind, bool)
- func ReadOnlyKind(k v1.Kind) bool
- func ReadOnlyWriter(k v1.Kind) string
- type ApplyOption
- type Backends
- type Bindings
- type Client
- func (c *Client) Apply(ctx context.Context, obj v1.Object, opts ...ApplyOption) (v1.Object, error)
- func (c *Client) Create(ctx context.Context, obj v1.Object) (v1.Object, error)
- func (c *Client) DeadLetter(ctx context.Context, ns v1.NamespaceName, id string) (deadletter.DeadLetter, error)
- func (c *Client) DeadLetters(ctx context.Context, ns v1.NamespaceName) ([]deadletter.DeadLetter, error)
- func (c *Client) Delete(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName, ...) error
- func (c *Client) DiscardDeadLetter(ctx context.Context, ns v1.NamespaceName, id string) error
- func (c *Client) Get(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName) (v1.Object, error)
- func (c *Client) HandoverKVStore(ctx context.Context, ns v1.NamespaceName, store, workflow v1.ObjectName) error
- func (c *Client) HoldStatus(ctx context.Context) (hold.Evidence, error)
- func (c *Client) List(ctx context.Context, kind v1.Kind, ns v1.NamespaceName) ([]v1.Object, error)
- func (c *Client) Logs(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, o LogsOptions) ([]logread.Line, error)
- func (c *Client) PlatformBackup(ctx context.Context) (runner.Status, error)
- func (c *Client) ReleaseHold(ctx context.Context, advance []string) error
- func (c *Client) ReleaseNamespaceHold(ctx context.Context, namespaces []string) error
- func (c *Client) ReplayDeadLetter(ctx context.Context, ns v1.NamespaceName, id string) error
- func (c *Client) RetryApp(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) error
- func (c *Client) RunLogs(ctx context.Context, ns v1.NamespaceName, run v1.ObjectName, o LogsOptions) ([]logread.Line, error)
- type Contract
- type DeleteOption
- type Dev
- type DevCatalog
- type LogsOptions
- type Manifest
- type ManifestDocument
- type Option
Constants ¶
const VoidSchema = `{"type":"null"}`
VoidSchema is the canonical void side (ADR-0090/0122): a contract side that carries no meaningful payload is the explicit JSON Schema {"type":"null"}, never an omission. Kept in pkg/sdk (not imported from internal/artifact) so funcdctl and the SDK share it without a package-boundary violation; the constant value matches internal/artifact.VoidSchema.
Variables ¶
This section is empty.
Functions ¶
func DecodeManifest ¶
DecodeManifest parses a single-document resource manifest (apiVersion/kind/metadata/spec) into the concrete v1.Object. An unknown/empty kind is a fault.Invalid, never a panic; so is a manifest holding more than one document (DecodeManifests decodes each).
func DecodeManifests ¶ added in v0.2.1
DecodeManifests parses a manifest that may hold several YAML documents separated by "---" into one v1.Object per document, in order. Empty and comment-only documents are skipped; a manifest with no document is a fault.Invalid.
func GenerateTypes ¶
GenerateTypes emits editor-facing declaration files from a manifest (ADR-0122 Decision 4): the FuncInput/FuncOutput payload types (from the contract JSON Schema) plus a typed binding context (from the declared aliases). python314 ⇒ a ".py" module (top-level-importable, no TYPE_CHECKING dance); nodejs22 ⇒ a ".d.ts" (imported with `import type`). This is DX-only — the platform never trusts these types; they exist to give the author editor autocomplete over the bounded funcd profile. The map is keyed by the file's basename; the caller writes each into the output directory.
func KindFromToken ¶
KindFromToken resolves a CLI token (plural, singular, or alias) to a v1.Kind.
func ReadOnlyKind ¶ added in v0.6.0
ReadOnlyKind reports whether the API serves only get and list for k, a kind a reconciler alone writes (ADR-0172, ADR-0200).
func ReadOnlyWriter ¶ added in v0.9.0
ReadOnlyWriter names the writer of a read-only kind, for the refusal of a write to it; "" if k is writable.
Types ¶
type ApplyOption ¶ added in v0.11.0
type ApplyOption func(*applyOptions)
ApplyOption tunes an Apply.
func DryRun ¶ added in v0.11.0
func DryRun() ApplyOption
DryRun makes Apply admit obj without storing it (ADR-0220): every request Apply sends carries dryRun=true, and the answer is the object as the write would store it, an App's with its plan in status.plan. Before its first dry-run write the client reads the server's OpenAPI document once; when the operation does not declare dryRun, Apply sends no write and fails, since an older server would ignore the flag and store the object.
type Backends ¶
type Backends struct {
// KV overrides the KVStore backend for ALL kv bindings ("memory" | a dsn/path override).
KV string `json:"kv,omitempty"`
// Blob overrides the Bucket backend for ALL blob bindings ("memory" | "file://…").
Blob string `json:"blob,omitempty"`
// Catalog overrides the CatalogService backend for ALL catalog bindings ("file://…", a local DuckLake).
Catalog string `json:"catalog,omitempty"`
}
Backends selects the driver `funcdctl dev` auto-provisions for each backend kind (ADR-0125 Decision 4), GLOBAL per kind. The built-in default is memory (ephemeral); a `file://…` value selects a local-durable backend under `--persist`.
type Bindings ¶
type Bindings struct {
Blob []v1.FunctionBlob `json:"blob,omitempty"`
KV []v1.FunctionKV `json:"kv,omitempty"`
Catalogs []v1.FunctionCatalog `json:"catalogs,omitempty"`
Links []v1.FunctionLink `json:"links,omitempty"`
Config []v1.ObjectName `json:"config,omitempty"`
Secrets []v1.ObjectName `json:"secrets,omitempty"`
}
Bindings reuses the v1alpha1 binding types 1:1 (ADR-0122 field map). The YAML shapes are those types' json shapes (alias/store/table, alias/bucket/prefix, …) — the capabilities the code uses at runtime, and the source GenerateTypes reads to emit the typed binding context.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a typed Go client over the funcd control-plane REST API.
func New ¶
New builds a Client. baseURL (e.g. "http://localhost:8080") is required.
func (*Client) Apply ¶
Apply create-or-replaces obj: PUT the named path; on a 404 (the object does not yet exist) POST the collection path to create it. Returns the stored object, or with DryRun the object as it would be stored.
func (*Client) Create ¶ added in v0.2.1
Create creates obj by POSTing the collection path, never replacing an existing object: a taken name is a fault.Conflict. An empty name with GenerateName set lets the server assign one.
func (*Client) DeadLetter ¶
func (c *Client) DeadLetter(ctx context.Context, ns v1.NamespaceName, id string) (deadletter.DeadLetter, error)
DeadLetter fetches one parked dead letter by id (ADR-0118), or fault.NotFound if absent.
func (*Client) DeadLetters ¶
func (c *Client) DeadLetters(ctx context.Context, ns v1.NamespaceName) ([]deadletter.DeadLetter, error)
DeadLetters lists a namespace's parked dead letters, newest first (ADR-0118). Tenant-scoped by the caller's identity (get/Sensor in the namespace) — the namespace is the authorized path segment.
func (*Client) Delete ¶
func (c *Client) Delete(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName, opts ...DeleteOption) error
Delete removes one object.
func (*Client) DiscardDeadLetter ¶
DiscardDeadLetter deletes a parked dead letter (ADR-0118) — a plain CRUD delete; absent is not an error server-side.
func (*Client) Get ¶
func (c *Client) Get(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName) (v1.Object, error)
Get fetches one object.
func (*Client) HandoverKVStore ¶ added in v0.5.0
func (c *Client) HandoverKVStore(ctx context.Context, ns v1.NamespaceName, store, workflow v1.ObjectName) error
HandoverKVStore makes workflow the owner of the kept KVStore store, so that Workflow binds it again (ADR-0178). The caller needs KVStore update and delete and Workflow get in ns.
func (*Client) HoldStatus ¶ added in v0.11.0
HoldStatus reads the platform hold's evidence (ADR-0206 Decision 8); admin-only.
func (*Client) Logs ¶
func (c *Client) Logs(ctx context.Context, ns v1.NamespaceName, fn v1.ObjectName, o LogsOptions) ([]logread.Line, error)
Logs reads a function's logs from the control-plane logs route (ADR-0084). The result is tenant-scoped to the caller's authenticated identity by the server (admin sees any namespace, developer/viewer only a bound one) — the namespace is the authorized path segment, never a client-asserted filter.
func (*Client) PlatformBackup ¶ added in v0.11.0
PlatformBackup reads the platform backup's status (ADR-0205); only an admin may.
func (*Client) ReleaseHold ¶ added in v0.11.0
ReleaseHold lifts the platform hold (ADR-0206 Decision 8). advance names blob EventSources, <ns>/<name>, whose listed keys are marked seen instead of replayed. Not held ⇒ fault.Conflict; an advance naming no blob event of an existing EventSource ⇒ fault.Invalid, both before any change.
func (*Client) ReleaseNamespaceHold ¶ added in v0.11.0
ReleaseNamespaceHold removes the hold a restore left on each namespace (ADR-0222 Decision 8): restore run's data marker and an ended in-place Restore's marker. POST …/hold/release with namespaces, which needs update on each Namespace; an in-place Restore still Pending or Running ⇒ fault.Conflict naming it.
func (*Client) ReplayDeadLetter ¶
ReplayDeadLetter re-injects a parked dead letter through the LIVE Sensor action path (ADR-0118 §3): ONE synchronous attempt. Success removes the entry (nil); failure re-parks it (Attempts reset) and returns the delivery error; a gone Sensor/action ⇒ fault.NotFound.
func (*Client) RetryApp ¶ added in v0.11.0
func (c *Client) RetryApp(ctx context.Context, ns v1.NamespaceName, name v1.ObjectName) error
RetryApp starts again, without waiting, the failed hook of the App's latest revision (ADR-0214 Decision 7). The caller needs App update in ns; fault.Conflict when the App has no failed hook, a hook call of it runs or it is paused.
func (*Client) RunLogs ¶
func (c *Client) RunLogs(ctx context.Context, ns v1.NamespaceName, run v1.ObjectName, o LogsOptions) ([]logread.Line, error)
RunLogs reads a whole workflow run's logs from the run-scoped control-plane route (ADR-0106): the server resolves the run's status.traceId and returns the namespace-wide, trace-filtered lines — every step function's output plus any sub-workflow child steps (one composition = one trace). Tenant-scoped by the caller's identity (get/WorkflowRun in the namespace). o.Step narrows to one step's function.
type Contract ¶
type Contract struct {
Input json.RawMessage `json:"input"`
Output json.RawMessage `json:"output"`
}
Contract is the manifest's inline I/O JSON Schema (ADR-0090/0122): both sides always present, a void side spelled VoidSchema. The two raw messages are gated (contract.Check) and baked schema-only.
type DeleteOption ¶ added in v0.4.0
type DeleteOption func(*deleteOptions)
DeleteOption tunes a Delete.
func Force ¶ added in v0.4.0
func Force() DeleteOption
Force deletes a ResourceGroup's members first, each under its own protections, then the group (ADR-0170). Delete refuses it with fault.Invalid for any other kind, before a request.
func IfVersion ¶ added in v0.11.0
func IfVersion(rv string) DeleteOption
IfVersion makes Delete conditional on rv: fault.Conflict when the object's resourceVersion differs (ADR-0210).
type Dev ¶
type Dev struct {
// Python is the interpreter `funcdctl dev` launches a python* handler with — a path relative to the
// manifest dir (e.g. `.venv/bin/python`) or absolute. Lets a project pin its virtualenv (which carries
// the handler's deps, ADR-0125's local-deps boundary) in the committable manifest instead of the
// FUNCD_PYTHON env. Precedence: FUNCD_PYTHON env > this > `python3` on PATH. GLOBAL per run (the first
// function's block is representative, like Backends).
Python string `json:"python,omitempty"`
// Node is the interpreter for a nodejs* handler (path relative to the manifest dir, or absolute).
// Precedence: FUNCD_NODE env > this > `node` on PATH.
Node string `json:"node,omitempty"`
// Catalog declares the PROVIDER side of a `catalogs:` binding so `funcdctl dev` can stand the
// CatalogService up locally, keyed by catalog name (matching a `bindings.catalogs[].catalog`). The
// consumer binding names WHICH catalog; this block gives dev the storage layout it cannot infer (which
// buckets/prefixes the DuckLake reads + owns) — the provider analogue of dev.backends. GLOBAL per run
// (first function that declares a given catalog wins). Empty ⇒ no catalog auto-provisioned.
Catalog map[string]DevCatalog `json:"catalog,omitempty"`
// Backends overrides the auto-provisioned backend per kind, GLOBALLY (not per binding). Empty ⇒ the
// built-in default (memory).
Backends Backends `json:"backends,omitempty"`
// Config carries inline ConfigMap values, keyed by ConfigMap name → {key: value}. Non-sensitive and
// committable (a plain env inject in dev — no ConfigMap CRD on disk).
Config map[string]map[string]string `json:"config,omitempty"`
// Secrets carries Secret values keyed by Secret name → key → "${ENV_VAR}". The value is NEVER read
// from the file — `funcdctl dev` resolves each ${ENV_VAR} from the process environment (a missing var
// fails fast), so funcdctl.yaml stays committable.
Secrets map[string]map[string]string `json:"secrets,omitempty"`
}
Dev is the funcdctl-dev-only manifest block (ADR-0125). `funcdctl dev` reads it to auto-provision a function's backing resources locally; `funcdctl push`/`types` ignore it. It is never a deploy field.
type DevCatalog ¶
type DevCatalog struct {
Blob []v1.FunctionBlob `json:"blob,omitempty"`
Catalog v1.CatalogRef `json:"catalog"`
}
DevCatalog is the funcdctl-dev provider declaration for one catalog (the storage layout dev cannot infer from a consumer binding). Blob is the catalog engine's bucket bindings (read + own — the SAME shape as Function.spec.blob); Catalog is the (bucket, prefix) the DuckLake catalog syncs under (owned by the catalog). funcdctl dev synthesizes a CatalogService (name = the map key) + a Quack-token Secret from it.
type LogsOptions ¶
type LogsOptions struct {
Since string // logread.SinceForms: a duration ("15m") or a timestamp ("2026-10-07T22:00:00.000Z"); "" ⇒ no lower bound
Severity string // minimum level (trace|debug|info|warn|error|fatal); "" ⇒ all
Limit int // max records (most-recent); <= 0 ⇒ the server default
Step string // RunLogs only (ADR-0106): narrow to one step's function (the --step drill-down); "" ⇒ all
}
LogsOptions are the optional filters for Client.Logs / Client.RunLogs (ADR-0084/0106).
type Manifest ¶
type Manifest struct {
// Runtime is the runtime class (e.g. python314, nodejs22) recorded as the push runtime annotation.
Runtime v1.RuntimeName `json:"runtime"`
// Handler is the entrypoint the shim resolves.
Handler string `json:"handler"`
// Main is the handler SOURCE FILE, relative to the manifest dir — the wrangler `main` convention
// (wrangler.toml `main = "src/entry.py"`). Empty ⇒ the default entry co-located with the manifest
// (handler.py for python*, handler.mjs otherwise, or `<stem>.py`/`<stem>.mjs` for a stem manifest).
// It lets a `<stem>.funcdctl.yaml` point at a NESTED handler (e.g. functions/extract/handler.py),
// so an existing per-function layout runs under `funcdctl dev` without flattening.
Main string `json:"main,omitempty"`
// Bindings holds blob/kv/catalogs/links/config/secrets — needed to run the function and to type its
// binding context (GenerateTypes). It is not a deploy field; it describes the capabilities the code uses.
Bindings Bindings `json:"bindings,omitempty"`
// Contract is the inline {input, output} JSON Schema; both sides always present (a void side is VoidSchema).
Contract Contract `json:"contract"`
// Dev is the funcdctl-dev-only block (ADR-0125): auto-provisioned/globally-overridable backends,
// inline ConfigMap values, and env-sourced Secret values. It is ADDITIVE and dev-only — `funcdctl
// push` and `funcdctl types` ignore it entirely (they read only the four fields above), so a
// funcdctl.yaml carrying a `dev:` block pushes and types identically to one without it.
Dev Dev `json:"dev,omitempty"`
}
Manifest is the parsed funcdctl.yaml (ADR-0122): a colocated, per-function CLIENT push/dev config (the client-side analogue of wrangler.toml), NOT a deploy manifest. It carries only what the client tooling needs to push, run, and type a function — the runtime, the handler, the bindings, and the inline I/O contract. Deploy concerns (name, namespace, scaling, placement) live on the hand-written Function CRD, never here. funcdctl reads it to `push` (bake the schema-only contract + record the runtime annotation), `types` (contract → .pyi/.d.ts + a typed binding context), and — later — `dev`.
func LoadManifest ¶
LoadManifest reads and parses a funcdctl.yaml at path, then structurally validates it. It does NOT gate the contract against the funcd profile (that is the CLI layer's contract.Check, which lives in internal/ and must not be imported here) — only shape rules a manifest cannot be useful without.
func (*Manifest) ContractSides ¶
ContractSides returns the two JSON Schema sides for the push-time gate + bake (contract.Check + artifact.ContractBlob). Both are mandatory (ADR-0090); a void side is VoidSchema, never nil.
type ManifestDocument ¶ added in v0.2.2
ManifestDocument is one decoded manifest document and its 1-based position in the manifest, counted as the decode errors count it (skipped empty and comment-only documents included).
func DecodeManifestDocuments ¶ added in v0.2.2
func DecodeManifestDocuments(data []byte) ([]ManifestDocument, error)
DecodeManifestDocuments is DecodeManifests that also returns each object's document number, so a caller can name the document a later error belongs to (issue #316).
type Option ¶
type Option func(*Client)
Option configures a Client (functional-options facade, ADR-0002).
func WithHTTPClient ¶
WithHTTPClient overrides the HTTP client (default http.DefaultClient). A client without a CheckRedirect policy gets the SDK's, which refuses a redirect that would change the method.