Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions doc/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,16 @@ below.
### Runtime flag

The passthrough is gated by `settings.enablePluginPadOptions`, default
`false`. Operators must opt in via `settings.json`:
`true`. Operators who want to lock plugins out of pad-wide state can flip
it in `settings.json`:

```json
{
"enablePluginPadOptions": true
"enablePluginPadOptions": false
}
```

When enabled, the server reflects the value to every client via
When enabled (the default), the server reflects the value to every client via
`clientVars.enablePluginPadOptions` so plugins can detect both *capable*
(static) and *active* (per-pad request) at the same point.

Expand Down
8 changes: 4 additions & 4 deletions settings.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -853,11 +853,11 @@
* accepting pad-wide values under plugin-namespaced keys matching
* /^ep_[a-z0-9_]+$/ (e.g. ep_table_of_contents). Values are validated
* (JSON-safe, 64 KB per key, 256 KB total) and broadcast to every
* connected client just like native pad-wide toggles. Disabled by
* default; flip to true once your plugins (e.g. ep_plugin_helpers'
* padToggle) require it. See doc/plugins.md.
* connected client just like native pad-wide toggles. Enabled by
* default; set to false to lock plugins out of pad-wide state. See
* doc/plugins.md.
**/
"enablePluginPadOptions": "${ENABLE_PLUGIN_PAD_OPTIONS:false}",
"enablePluginPadOptions": "${ENABLE_PLUGIN_PAD_OPTIONS:true}",

/*
* Optional privacy banner shown once the pad loads. Disabled by default.
Expand Down
2 changes: 1 addition & 1 deletion src/node/utils/PluginCapabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// True when applyPadSettings (client + server) preserves keys matching
// /^ep_[a-z0-9_]+$/ on pad.padOptions. The runtime gate is
// settings.enablePluginPadOptions (default false), mirrored to clients via
// settings.enablePluginPadOptions (default true), mirrored to clients via
// clientVars.enablePluginPadOptions. See doc/plugins.md for the full
// contract (key namespace, validation, size caps).
export const padOptionsPluginPassthrough = true;
10 changes: 5 additions & 5 deletions src/node/utils/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,11 @@ const settings: SettingsType = {
updateServer: "https://static.etherpad.org",
enableDarkMode: true,
enablePadWideSettings: true,
// New plugin-padOption passthrough is opt-in per AGENTS.MD §52 ("New
// features should be placed behind feature flags and disabled by
// default"). Flip to true to let plugins (e.g. ep_plugin_helpers'
// padToggle) ride the existing padoptions broadcast/persist rail.
enablePluginPadOptions: false,
// Lets plugins (e.g. ep_plugin_helpers' padToggle / padSelect) ride the
// existing padoptions broadcast/persist rail to store pad-wide options
// under ep_* keys. Operators who want to lock plugin-driven pad-wide
// state out can set this to false in settings.json.
enablePluginPadOptions: true,
allowPadDeletionByAllUsers: false,
privacyBanner: {
enabled: false,
Expand Down
6 changes: 3 additions & 3 deletions src/tests/backend/specs/Pad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ describe(__filename, function () {
});
afterEach(function () { console.warn = warnSpy; });

describe('with enablePluginPadOptions = true', function () {
describe('with enablePluginPadOptions = true (default)', function () {
before(function () { settings.enablePluginPadOptions = true; });

it('preserves ep_* keys verbatim so plugins can ride padoptions', function () {
Expand Down Expand Up @@ -285,10 +285,10 @@ describe(__filename, function () {
});
});

describe('with enablePluginPadOptions = false (default)', function () {
describe('with enablePluginPadOptions = false (operator opt-out)', function () {
before(function () { settings.enablePluginPadOptions = false; });

it('drops every ep_* key — feature flag is opt-in', function () {
it('drops every ep_* key — operator has opted out of plugin pad-wide state', function () {
const ps: any = Pad.Pad.normalizePadSettings({
ep_table_of_contents: {enabled: true},
ep_font_color: 'red',
Expand Down
Loading