Summary
Dashboard header actions[] (and widget actionUrl) can reference actions or routes that do not exist. Nothing in os validate / os build flags them, so they ship as buttons that silently do nothing when clicked. This is the ADR-0049 "enforce-or-remove" principle applied to references rather than to properties.
Surfaced while reviewing a production app on 16.0.0-rc.1.
Repro
Dashboard header actions such as:
header: {actions: [{label: 'Export PDF',actionType: 'script',actionUrl: 'export_dashboard_pdf'},{label: 'New Deal',actionType: 'modal',actionUrl: 'create_opportunity'},{label: 'Forecast',actionType: 'url',actionUrl: '/reports/forecast'},],}export_dashboard_pdf / create_opportunity are script / modal targets but no such action is defined anywhere in the stack./reports/forecast is a url target that matches no registered report/view/object route.
All of these pass os validate and os build; at runtime the buttons render and do nothing. Authoring a non-existent target is a false affordance — the exact failure mode ADR-0049 exists to prevent for metadata properties.
Proposed check
Add reference-integrity validation for action targets:
actionType: 'script' | 'modal' → error/warn unless actionUrl resolves to a defined action.actionType: 'url' → warn unless the path resolves to a registered view / report / object route (in-app route shape).
Applies to dashboard header.actions[], widget actionUrl, and any other surface that references an action/route by id or path.
Acceptance criteria
- A dashboard action referencing an undefined
script/modal action fails validation with a message naming the dashboard, button label, and unresolved target. - A
url action pointing at a non-existent in-app route is at least warned. - Valid references (defined action / real route) pass.
- Fixture coverage for defined vs dangling targets.
Lower priority than the two runtime-crash cases, but closes the same "declared ≠ enforced" gap for references.
Related shift-left checks from the same 14.7 → 16 upgrade: #3365, #3366, #3367.
Summary
Dashboard header
actions[](and widgetactionUrl) can reference actions or routes that do not exist. Nothing inos validate/os buildflags them, so they ship as buttons that silently do nothing when clicked. This is the ADR-0049 "enforce-or-remove" principle applied to references rather than to properties.Surfaced while reviewing a production app on
16.0.0-rc.1.Repro
Dashboard header actions such as:
export_dashboard_pdf/create_opportunityarescript/modaltargets but no such action is defined anywhere in the stack./reports/forecastis aurltarget that matches no registered report/view/object route.All of these pass
os validateandos build; at runtime the buttons render and do nothing. Authoring a non-existent target is a false affordance — the exact failure mode ADR-0049 exists to prevent for metadata properties.Proposed check
Add reference-integrity validation for action targets:
actionType: 'script' | 'modal'→ error/warn unlessactionUrlresolves to a defined action.actionType: 'url'→ warn unless the path resolves to a registered view / report / object route (in-app route shape).Applies to dashboard
header.actions[], widgetactionUrl, and any other surface that references an action/route by id or path.Acceptance criteria
script/modalaction fails validation with a message naming the dashboard, button label, and unresolved target.urlaction pointing at a non-existent in-app route is at least warned.Lower priority than the two runtime-crash cases, but closes the same "declared ≠ enforced" gap for references.
Related shift-left checks from the same 14.7 → 16 upgrade: #3365, #3366, #3367.