Skip to content

PluginContext

An app imports nothing from the host. What it needs arrives here.

async handler(args, ctx: PluginContext) { /* … */ }
Member Available in What it is
pluginId tools, jobs Your own id.
organizationId tools The customer being worked for.
settings tools Their configuration, validated, defaults applied.
settingsSavedAt tools When they last saved the panel — the human gesture, null if never.
storage tools Key/value private to your app and this organisation.
shared tools, jobs Key/value private to your app, common to every organisation.
http tools, jobs The only way to the network, limited to allowedHosts.
secrets tools, jobs The host’s environment variables you declared. core apps only.
log tools, jobs info, warn, error, with structured metadata.
now() tools, jobs Injected clock. Use it instead of new Date(): it’s what makes your tests deterministic.

A job’s context is deliberately narrower — no organisation, no settings, no per-tenant storage — because a job runs once for the whole platform.

Even where, running in-process, it wouldn’t need to be. PluginContext is the boundary that becomes a network call the day third-party apps run elsewhere, and every argument crossing it is serializable for the same reason.

secrets is the one exception, synchronous and non-serializable on purpose: it’s the thing that must not cross that boundary. A verified or external app brings its own credentials — it never receives ours.

Not “when the row was touched”: when a person last confirmed the configuration.

It exists for values that are only true for a while. A gold price typed by hand is worth something today and nothing next week, and an app that prices with it needs to know whether it was confirmed today or forgotten in March.

import { createHarness } from "@prezzando/plugin-sdk/testing";
const harness = createHarness(manifest, {
settings: { trade: "cartongesso" },
now: new Date("2026-08-20T08:00:00Z"),
});
const result = await harness.runTool("gold_price", { fineness: "750" });

Storage is in memory, the clock is fixed, and the network is closed unless you open it. It’s the same harness the CLI uses for run and job.