Skip to content

1.0.0: Let plugins put their own pages in the panel

Choose a tag to compare

@bobicloudvision bobicloudvision released this 10 Sep 19:35
· 11 commits to main since this release
A plugin describes a page and the panel draws it with its own components. It
never emits HTML.

That is the whole reason to prefer this over an iframe. The page matches the
rest of the panel, follows the operator's theme, works at phone width, and is
escaped by the panel, so a plugin cannot inject markup into the panel even by
accident: there is no markup to inject. The panel already iframes CloudLinux's
UI, and the coupling that took (knowing its bundles, its config file, its
feature gates) is the thing this design exists to avoid.

Page, Section, Stat, Table, Form, Alert and Text cover what a plugin page
actually needs. Colours are the panel's semantic names rather than hex values,
so a plugin cannot fight the theme or produce something unreadable in dark
mode, and column types tell the panel how to format a value rather than the
plugin formatting it in the wrong timezone.

Iframes stay available for a terminal or an existing single-page app, declared
as render: iframe and proxied by the panel so the plugin still needs no public
port.

Security-relevant decisions:

The viewer identity travels in the same signed envelope as a hook delivery,
because it is what a plugin scopes its data by. An unsigned one would be a way
to read another account's data through a plugin. clientFor() now takes a page
request as well as a hook, so scoping to the account being viewed stays the
path of least resistance.

Only registered pages and actions are reachable. A request naming anything
else is refused before plugin code runs, so an action is not callable because
someone guessed it.

A secret field drops its value on serialisation whatever the plugin set, so a
stored credential is never served back to a browser. Show that one is set with
the placeholder instead.

A handler that throws returns a flat message; the detail goes to the plugin
log rather than to the person looking at the page.

Poll intervals floor at five seconds, since every poll is a request to the
plugin.