wisewigdocs

Plugins

Plugins extend a defined framework surface; they do not alter arbitrary HTML or receive ambient infrastructure credentials.

Sandboxed plugins by default

Third-party and marketplace plugins should run in an isolated sandbox by default. The sandbox exposes a capability-gated bridge: undeclared content, media, forms, settings, network, and storage APIs are absent rather than merely rejected at a later call. Plugins never receive environment variables, filesystem access, D1/R2/DO bindings, or direct network primitives.

Every plugin has a validated manifest with a scoped identity, semantic version, capabilities, storage/index requests, hooks, UI surface, and MCP tools, resources, and prompts. Network access requires both network.fetch and an explicit hostname allowlist. Sandboxed admin UI is a declarative block tree rendered by the host; sandboxed plugins cannot ship browser JavaScript/React controls. Runtime enforcement must reject an undeclared capability even for an installed plugin. A public plugin MCP primitive is restricted to the public_content data scope; it cannot carry a permission. Private primitives must declare a WiseWig permission and data scope. Form submissions, engagement aggregates, and personal data are private-only, with personal data requiring the elevated engagement.export permission.

The initial executable enforcement is documented in plugin runtime boundaries.

Native plugins are exceptional

Native plugins run in the same process as a site’s deployed theme and can ship Astro/React code where a developer genuinely needs that power. They are for developer-controlled code, versioned and deployed with the site—not one-click marketplace installation. Capability declarations remain useful policy, but native code is not an isolation boundary: it can access the runtime directly. The native PluginRuntime explicitly refuses to execute a sandboxed manifest.

The Cloudflare reference accepts only signed ECDSA P-256 releases from configured registry keys. The signature covers the normalized manifest, provenance, artifact, and forward-only declarative migrations; the declared SHA-256 artifact digest is recomputed before installation. Native packages cannot use this route. The management UI summarizes capabilities and MCP tools before confirmation, and install/upgrade/enable/disable/rollback/uninstall operations use plugin.manage, durable idempotency, and audit.

Alpha sandbox artifacts are bounded declarative hook programs (require-field, max-string, and deny), not arbitrary JavaScript. They execute in the separately deployed wise-wig-plugin-sandbox Worker, whose only binding is its own artifact Durable Object. It has no site D1, R2, session, tenant workspace, or outbound-network bridge. Artifact state is addressed by verified digest, so an upgrade for one site cannot silently replace another site’s selected artifact. A future Dynamic Worker runner can implement the same boundary for vetted code packages.

Tenant workspace SQLite stores the active and previous release, migration ledger, enabled state, declared collections, and quota-metered plugin records. Upgrades retain one rollback release. Alpha migrations only create declared collections; destructive migrations are rejected so manifest rollback does not pretend it can restore deleted data. Uninstall removes that plugin’s namespaced records and migration ledger.

Hook policy

Hooks validate or react to lifecycle events. They cannot mutate published state directly, block indefinitely, or make the editor wait for nonessential external work. beforeSave and beforePublish hooks are bounded validation points; delivery, indexing, and integrations run after the committed command.