mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-10 03:51:54 +00:00
Canonicalize monitored-system commercial copy
This commit is contained in:
parent
b670cf2341
commit
fa680da8dd
13 changed files with 48 additions and 19 deletions
|
|
@ -224,6 +224,10 @@ show the counted monitored systems coming from agent-backed infrastructure, but
|
|||
the shared API helper must expose the canonical unified-resource grouping
|
||||
explanation instead of rebuilding count reasons from install or registration
|
||||
state.
|
||||
Lifecycle-adjacent workspace copy must also keep the same commercial framing:
|
||||
infrastructure operations may point operators to Pulse Pro for billing, but it
|
||||
must describe that boundary in monitored-system, plan-limit, and license-status
|
||||
terms rather than reviving legacy agent-allocation language.
|
||||
That same boundary now also assumes canonical resource payloads preserve
|
||||
shared facet totals through `facetCounts`, so the resource list and detail
|
||||
surfaces can keep row summaries aligned without re-inferring totals from
|
||||
|
|
|
|||
|
|
@ -328,7 +328,13 @@ instead of redefining retail plan facts or counted-unit policy locally.
|
|||
That same counted-unit boundary also owns the disclosure rule for retail copy:
|
||||
default billing and pricing surfaces should use concise monitored-system copy,
|
||||
while the full counted-unit definition appears only behind explicit disclosure
|
||||
such as `What counts?` instead of sitting as always-visible explanatory chrome.
|
||||
such as `View counting rules` instead of sitting as always-visible explanatory
|
||||
chrome.
|
||||
Those same billing-facing surfaces must also describe the commercial contract in
|
||||
customer terms: monitored systems, plan limits, subscription status, and
|
||||
license status. They must not revive legacy `installed-agent` wording or vague
|
||||
internal nouns like `allocation` once the monitored-system billing model is the
|
||||
canonical product truth.
|
||||
The self-hosted pricing page should therefore stay focused on plan cards,
|
||||
upgrade paths, and the comparison table rather than rendering a separate
|
||||
counted-unit explainer card beneath the tier grid.
|
||||
|
|
|
|||
|
|
@ -668,6 +668,10 @@ shared banner or shared settings shell is explaining self-hosted plan caps,
|
|||
the operator-facing commercial term must follow the monitored-system model even
|
||||
if explicit legacy-v5 compatibility helpers still decode older alias fields at
|
||||
import boundaries.
|
||||
That same settings-shell framing must stay in customer language. Shared headers
|
||||
and descriptions should talk about monitored-system limits, plan limits, and
|
||||
subscription or license status instead of reviving legacy `installed-agent`
|
||||
terms or vague internal nouns like `allocation`.
|
||||
That banner boundary now also owns the canonical monitored-system naming
|
||||
surface directly: the shared warning component path and exported symbol are
|
||||
`MonitoredSystemLimitWarningBanner`, and future work may not reintroduce an
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ describe('MonitoredSystemDefinitionDisclosure', () => {
|
|||
));
|
||||
|
||||
expect(screen.getByText('Billing is based on monitored systems.')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'What counts?' })).toHaveAttribute(
|
||||
expect(screen.getByRole('button', { name: 'View counting rules' })).toHaveAttribute(
|
||||
'aria-expanded',
|
||||
'false',
|
||||
);
|
||||
|
|
@ -18,9 +18,9 @@ describe('MonitoredSystemDefinitionDisclosure', () => {
|
|||
screen.queryByText(/a monitored system is a top-level machine or cluster/i),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'What counts?' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'View counting rules' }));
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Hide details' })).toHaveAttribute(
|
||||
expect(screen.getByRole('button', { name: 'Hide counting rules' })).toHaveAttribute(
|
||||
'aria-expanded',
|
||||
'true',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ export const InfrastructureWorkspace: Component<InfrastructureWorkspaceProps> =
|
|||
connections, and control which infrastructure surfaces are actively reporting.
|
||||
</p>
|
||||
<p class="text-sm text-muted">
|
||||
Billing, installed-agent allocation, and Pulse Pro entitlement state live in Pulse
|
||||
Pro, not here.
|
||||
Billing, monitored-system limits, and Pulse Pro license status live in Pulse Pro,
|
||||
not here.
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export const ProLicensePanel: Component = () => {
|
|||
<div class="space-y-6">
|
||||
<CommercialBillingShell
|
||||
title="Pulse Pro"
|
||||
description="Manage self-hosted billing, monitored-system limits, and the activation state that controls paid features."
|
||||
description="Manage self-hosted billing, monitored-system limits, and Pulse Pro license status."
|
||||
icon={<ShieldCheck class="w-5 h-5" />}
|
||||
action={
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ describe('InfrastructureWorkspace', () => {
|
|||
expect(screen.getByText('Infrastructure operations')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Billing, installed-agent allocation, and Pulse Pro entitlement state live in Pulse Pro, not here.',
|
||||
'Billing, monitored-system limits, and Pulse Pro license status live in Pulse Pro, not here.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: 'Install on a host' })).toHaveAttribute(
|
||||
|
|
|
|||
|
|
@ -183,15 +183,15 @@ describe('MonitoredSystemLedgerPanel', () => {
|
|||
expect(screen.getByText('Monitored System Ledger')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Review the monitored systems currently counting toward your Pulse Pro allocation.',
|
||||
'Review the monitored systems currently counted against your Pulse Pro plan limit.',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'What counts?' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'View counting rules' })).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(/a monitored system is a top-level machine or cluster pulse actively monitors/i),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'What counts?' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'View counting rules' }));
|
||||
|
||||
expect(
|
||||
screen.getByText(/a monitored system is a top-level machine or cluster pulse actively monitors/i),
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ describe('ProLicensePanel', () => {
|
|||
screen.queryByText(/a monitored system is a top-level machine or cluster/i),
|
||||
).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'What counts?' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'View counting rules' }));
|
||||
|
||||
expect(
|
||||
screen.getByText(/a monitored system is a top-level machine or cluster/i),
|
||||
|
|
|
|||
|
|
@ -1039,6 +1039,21 @@ describe('Settings architecture guardrails', () => {
|
|||
expect(SETTINGS_HEADER_META['infrastructure-operations'].description).toContain('Pulse Pro');
|
||||
});
|
||||
|
||||
it('keeps billing-related shell framing on monitored-system commercial terms', () => {
|
||||
expect(SETTINGS_HEADER_META['infrastructure-operations'].description).toContain(
|
||||
'monitored-system limits',
|
||||
);
|
||||
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['organization-billing'].description).toContain(
|
||||
'subscription status',
|
||||
);
|
||||
expect(SETTINGS_HEADER_META['organization-billing'].description).toContain('plan limits');
|
||||
});
|
||||
|
||||
it('keeps shell titles aligned with the leading settings panel on key top-level surfaces', () => {
|
||||
for (const { tab, title, source } of canonicalShellTitleExpectations) {
|
||||
expect(SETTINGS_HEADER_META[tab].title, `${tab} should keep its shell title canonical`).toBe(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const SETTINGS_HEADER_META: SettingsHeaderMetaMap = {
|
|||
'infrastructure-operations': {
|
||||
title: 'Infrastructure Operations',
|
||||
description:
|
||||
'Bring infrastructure into Pulse, manage direct Proxmox connections, and control which systems are actively reporting. Billing and installed-agent allocation live in Pulse Pro.',
|
||||
'Bring infrastructure into Pulse, manage direct Proxmox connections, and control which systems are actively reporting. Billing and monitored-system limits live in Pulse Pro.',
|
||||
},
|
||||
'system-general': {
|
||||
title: 'General',
|
||||
|
|
@ -39,7 +39,7 @@ export const SETTINGS_HEADER_META: SettingsHeaderMetaMap = {
|
|||
'system-billing': {
|
||||
title: 'Pulse Pro',
|
||||
description:
|
||||
'Manage self-hosted Pulse Pro billing, installed-agent allocation, and the activation state that controls paid features.',
|
||||
'Manage self-hosted Pulse Pro billing, monitored-system limits, and license status for paid features.',
|
||||
},
|
||||
'organization-overview': {
|
||||
title: 'Organization Overview',
|
||||
|
|
@ -56,7 +56,7 @@ export const SETTINGS_HEADER_META: SettingsHeaderMetaMap = {
|
|||
'organization-billing': {
|
||||
title: 'Billing & Usage',
|
||||
description:
|
||||
'Review your organization plan, usage against limits, and the allocation state that controls paid access.',
|
||||
'Review your organization plan, usage against plan limits, and subscription status for paid access.',
|
||||
},
|
||||
'organization-billing-admin': {
|
||||
title: 'Billing Admin',
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ describe('PricingV6', () => {
|
|||
expect(
|
||||
screen.queryByText('Billing is based on monitored systems. Child resources are included.'),
|
||||
).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'What counts?' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'View counting rules' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('imports the shared self-hosted pricing model instead of redefining it locally', () => {
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@ export interface SelfHostedFeatureRow {
|
|||
export const SELF_HOSTED_MONITORED_SYSTEMS_BRIEF =
|
||||
'Billing is based on monitored systems. Child resources are included.';
|
||||
|
||||
export const SELF_HOSTED_MONITORED_SYSTEMS_DISCLOSURE_LABEL = 'What counts?';
|
||||
export const SELF_HOSTED_MONITORED_SYSTEMS_DISCLOSURE_LABEL = 'View counting rules';
|
||||
|
||||
export const SELF_HOSTED_MONITORED_SYSTEMS_HIDE_LABEL = 'Hide details';
|
||||
export const SELF_HOSTED_MONITORED_SYSTEMS_HIDE_LABEL = 'Hide counting rules';
|
||||
|
||||
export const SELF_HOSTED_MONITORED_SYSTEMS_DEFINITION =
|
||||
'A monitored system is a top-level machine or cluster Pulse actively monitors. Each system counts once no matter how Pulse collects it. Child resources like VMs, containers, pods, disks, backups, and services are included.';
|
||||
|
||||
export const SELF_HOSTED_MONITORED_SYSTEM_LEDGER_DESCRIPTION =
|
||||
'Review the monitored systems currently counting toward your Pulse Pro allocation.';
|
||||
'Review the monitored systems currently counted against your Pulse Pro plan limit.';
|
||||
|
||||
export const SELF_HOSTED_PLAN_DEFINITIONS: readonly SelfHostedPlanDefinition[] = [
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue