typress
An editorial workshop.日本語

Plugins

Plugins ship as .tpkg too. The difference from themes is the manifest's capabilities field — every privilege a plugin requests is declared and shown to the operator at install time.

Capabilities

A plugin lists the capabilities it wants in manifest.json. The host hands the plugin only the bridge objects matching those capabilities, over a Cap'n Web RPC. Anything not declared simply isn't there to call.

  • posts:read / posts:write — read or write posts
  • hooks:register — subscribe to typed hook events
  • blocks:register — register custom blocks (v1.1)
  • settings:read:own / settings:write:own — settings under the plugin's namespace
  • http:fetch:allowlist — egress to a fixed allowlist (specified in the manifest)

Trusted-key scoping (ADR-002)

Each trusted key can be scoped to specific plugin IDs and capabilities. An empty scope means "trust everything signed by this key" (back-compat). With explicit scopes, a leaked key can't immediately be used to ship plugins under different IDs or with privileges the operator didn't intend.

Execution model (ADR-001)

Plugins do not share the host process. They run as Bun.spawn child processes. OOMs, crashes, and infinite loops are contained in the child; the host stays up. Each child has a 5-second init deadline; three consecutive start failures auto-flips enabled=0 (auto-quarantine). The full boundary is covered in Security.

Sample: examples/plugin-greeter

Reference plugin that requests posts:read / posts:write, creates a single welcome post on first run, and is otherwise idempotent.

bun tools/tpkg/src/main.ts pack examples/plugin-greeter
bun tools/tpkg/src/main.ts sign \
  examples/plugin-greeter/com.typress.greeter-0.1.0.tpkg \
  --key dev