You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(plugins): read-only taxonomy access via new taxonomies:read capability (emdash-cms#1719)
* feat(plugins): read-only taxonomy access via new taxonomies:read capability
* test(cloudflare): cover PluginBridge taxonomy methods
Review follow-up: capability enforcement, locale/taxonomy filter SQL
wiring, and D1 row mapping (JSON parsing, int→bool, nullable columns)
for taxonomyList/taxonomyTerms/taxonomyEntryTerms.
* test/fix: review follow-ups for taxonomies:read
Guard the in-process collections JSON parse like both bridges (an
in-process plugin no longer crashes on malformed definition data), and
extend the workerd conformance suite to taxonomy/terms and
taxonomy/entryTerms: capability gating, locale filtering, data JSON
parsing, and the pivot join on translation_group.
Adds a `taxonomies:read` plugin capability with read-only taxonomy access: plugins that declare it get `ctx.taxonomies` to list taxonomy definitions (`getAll()`), fetch the terms of a taxonomy (`getTerms()`), and read the terms assigned to a content entry (`getEntryTerms()`) — in-process and in both sandbox runners.
|`network:request`|`ctx.http.fetch()` — restricted to `allowedHosts`|
@@ -44,6 +45,7 @@ Declare only what the plugin actually needs. Capability declarations are also wh
44
45
A few things worth knowing:
45
46
46
47
-**Implications.**`content:write` automatically implies `content:read`; `media:write` implies `media:read`; `network:request:unrestricted` implies `network:request`. You don't need to list both.
48
+
-**Taxonomies are a separate, read-only surface.**`taxonomies:read` grants access to taxonomy definitions, their terms, and the terms assigned to an entry via `ctx.taxonomies`. It is independent of `content:read` — declare both if the plugin reads content *and* its classification. There is no taxonomy *write* access from plugins.
47
49
-**`network:request:unrestricted` exists for user-configured URLs.** A webhook plugin where the operator types in the destination URL needs to reach hosts that aren't in the manifest. Plugins that always call known APIs should use `network:request` + `allowedHosts`.
48
50
-**`email:send` is gated by configuration, not just the capability.** A plugin can declare `email:send`, but `ctx.email` will only be populated if some other plugin has registered an `email:deliver` transport.
49
51
@@ -69,7 +71,7 @@ When a sandbox runner is active, the runtime enforces:
69
71
70
72
<Steps>
71
73
72
-
1.**Capability gating.** The PluginContext factory only populates `ctx.content`, `ctx.media`, `ctx.http`, `ctx.users`, `ctx.email` when the corresponding capability is declared. Calling a method on an undeclared capability isn't possible — there's no object there.
74
+
1.**Capability gating.** The PluginContext factory only populates `ctx.content`, `ctx.taxonomies`, `ctx.media`, `ctx.http`, `ctx.users`, `ctx.email` when the corresponding capability is declared. Calling a method on an undeclared capability isn't possible — there's no object there.
73
75
74
76
2.**Storage and KV scoping.** Every storage and KV operation is scoped to the plugin's slug. A plugin can't read another plugin's KV or its storage collections, and it can only access storage collections it declared in the manifest.
0 commit comments