From 2935440e1ea7ef4f434e8e15db80bf343dcf034d Mon Sep 17 00:00:00 2001 From: rcourtman Date: Fri, 27 Mar 2026 08:24:35 +0000 Subject: [PATCH] Align Pulse Pro route header copy --- .../v6/internal/subsystems/cloud-paid.md | 3 +++ .../v6/internal/subsystems/frontend-primitives.md | 13 +++++++++++++ .../Settings/__tests__/settingsArchitecture.test.ts | 6 ++++-- .../src/components/Settings/settingsHeaderMeta.ts | 4 ++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/cloud-paid.md b/docs/release-control/v6/internal/subsystems/cloud-paid.md index 9c4cd7473..9c11673ed 100644 --- a/docs/release-control/v6/internal/subsystems/cloud-paid.md +++ b/docs/release-control/v6/internal/subsystems/cloud-paid.md @@ -485,6 +485,9 @@ That same boundary also owns the shell and section framing copy for the self-hosted Pro billing surface. `ProLicensePanel.tsx` must consume shared presentation for its shell title/description, refresh CTA label, and section headings rather than carrying those commercial labels inline. +The same description should also feed the `system-billing` route header +metadata so the settings shell and the route header do not narrate the same +commercial surface differently. Paid Pulse Pro v5 grandfathering is now part of that same canonical boundary: when a recurring v5 customer migrates into v6, billing persistence, entitlement evaluation, renewal handling, and Pro-license presentation must diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index 07066d2c7..8e323dca2 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -154,6 +154,10 @@ work extends shared components instead of creating new local variants. plus `tests/integration/tests/15-settings-shell-consistency.spec.ts` 3. Update this contract when a new canonical UI pattern is adopted 4. Remove local forks after the shared primitive is introduced +5. When a settings route header and a top-level settings shell describe the same + commercial surface, keep them on the same shared presentation owner instead + of allowing route metadata in `settingsHeaderMeta.ts` to drift into + independent copy. ## Current State @@ -1240,6 +1244,15 @@ is the shell, `useSSOProvidersState.ts` owns the reactive/API lifecycle, and `frontend-modern/src/components/Settings/UpdatesSettingsPanel.tsx` must keep page-shell titles, descriptions, and lead panel framing aligned instead of letting navigation/header labels drift away from the actual settings surface. +The self-hosted Pulse Pro route header metadata for +`frontend-modern/src/components/Settings/settingsHeaderMeta.ts` is part of that +same shell boundary as +`frontend-modern/src/components/Settings/ProLicensePanel.tsx` and the shared +commercial presentation owner in +`frontend-modern/src/utils/licensePresentation.ts`; the `system-billing` +header description must reuse +`SELF_HOSTED_PRO_BILLING_PRESENTATION.shellDescription` so the route header and +the billing shell do not narrate the same commercial surface differently. `frontend-modern/src/components/Settings/NetworkSettingsPanel.tsx` is now a shell only. `frontend-modern/src/components/Settings/NetworkDiscoverySection.tsx` owns discovery controls and shared subnet presets, while diff --git a/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts b/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts index c46c4b0c4..ddd5d9e30 100644 --- a/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts +++ b/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from 'vitest'; +import { SELF_HOSTED_PRO_BILLING_PRESENTATION } from '@/utils/licensePresentation'; import settingsSource from '../Settings.tsx?raw'; import settingsDialogsSource from '../SettingsDialogs.tsx?raw'; import settingsShellSource from '../SettingsPageShell.tsx?raw'; @@ -1271,8 +1272,9 @@ describe('Settings architecture guardrails', () => { expect(SETTINGS_HEADER_META['infrastructure-operations'].description).not.toContain( 'installed-agent', ); - expect(SETTINGS_HEADER_META['system-billing'].description).toContain('license status'); - expect(SETTINGS_HEADER_META['system-billing'].description).not.toContain('allocation'); + expect(SETTINGS_HEADER_META['system-billing'].description).toBe( + SELF_HOSTED_PRO_BILLING_PRESENTATION.shellDescription, + ); expect(SETTINGS_HEADER_META['organization-billing'].description).toContain( 'subscription status', ); diff --git a/frontend-modern/src/components/Settings/settingsHeaderMeta.ts b/frontend-modern/src/components/Settings/settingsHeaderMeta.ts index 837f7c1ab..3630af2dc 100644 --- a/frontend-modern/src/components/Settings/settingsHeaderMeta.ts +++ b/frontend-modern/src/components/Settings/settingsHeaderMeta.ts @@ -1,4 +1,5 @@ import type { SettingsHeaderMetaMap } from './settingsNavigationModel'; +import { SELF_HOSTED_PRO_BILLING_PRESENTATION } from '@/utils/licensePresentation'; export const SETTINGS_HEADER_META: SettingsHeaderMetaMap = { proxmox: { @@ -38,8 +39,7 @@ export const SETTINGS_HEADER_META: SettingsHeaderMetaMap = { }, 'system-billing': { title: 'Pulse Pro', - description: - 'Manage self-hosted Pulse Pro billing, monitored-system limits, and license status for paid features.', + description: SELF_HOSTED_PRO_BILLING_PRESENTATION.shellDescription, }, 'organization-overview': { title: 'Organization Overview',