Security hardening, multi-site portability, and a documentation and API-surface sweep

This commit is contained in:
2026-08-14 16:28:34 -04:00
parent 72f8da0e58
commit 265ca2eb01
76 changed files with 3684 additions and 811 deletions

View File

@@ -205,15 +205,35 @@ class BasePlugin(ABC):
def get_dashboard_widgets(self) -> List[Dict]:
"""
Return dashboard widget definitions.
Return dashboard card definitions.
Each widget: {
'name': str,
'component': str, # Frontend component name
'endpoint': str, # API endpoint for data
'size': str, # 'small', 'medium', 'large'
'position': int # Order on dashboard
DATA AND SHAPE, not a component name. The card is drawn by one of core's
generic renderers; the plugin says what to show, where it comes from and
how to link it.
Contract 0.19.0 replaced a shape that named a Vue component per widget.
That could not survive a lean build - a plugin's component may never be
staged into the frontend bundle (ADR-013) - and in practice five plugins
declared widgets pointing at components nobody had written, which
rendered as nothing at all. It is the same correction ADR-010 already
made for asset panels.
Each card: {
'id': str, # stable, unique across plugins
'title': str, # heading
'endpoint': str, # API path the card fetches its own data from
'render': str, # core renderer: 'exceptions' | 'list' | 'stat'
'severity': str, # 'critical' | 'warning' | 'info' - orders cards
'permission': str, # card is hidden without it
'empty': str, # 'hide' when nothing to report, or empty text
'position': int, # order within a severity
'viewall': str, # optional route behind the card heading
'map': dict, # optional field mapping for the renderer,
# e.g. {'title': 'hostname', 'detail': 'entryname'}
}
`empty: 'hide'` is not cosmetic. A card that reports "nothing wrong"
every day teaches people to stop reading the page.
"""
return []