From 4e7d7ddb4f8fe16b0fe4ccdbeaa3b65b2b4a88c7 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Sat, 13 Jun 2026 17:36:27 +0100 Subject: [PATCH] Converge connection editor notices on CalloutCard --- .../v6/internal/subsystems/agent-lifecycle.md | 6 +- .../v6/internal/subsystems/api-contracts.md | 4 + .../subsystems/frontend-primitives.md | 11 ++ .../v6/internal/subsystems/registry.json | 22 ++++ .../scripts/shared-template-registry.json | 102 ++++++++++++++++++ .../ConnectionEditor/AddressProbeStep.tsx | 74 +++++++------ .../AvailabilityTargetSlot.tsx | 44 ++++---- .../CredentialSlots/TrueNASCredentialSlot.tsx | 25 +++-- .../CredentialSlots/VMwareCredentialSlot.tsx | 40 ++++--- .../__tests__/settingsArchitecture.test.ts | 32 ++++++ .../SharedPrimitives.guardrails.test.ts | 87 +++++++++++++++ .../release_control/subsystem_lookup_test.py | 2 +- 12 files changed, 366 insertions(+), 83 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/agent-lifecycle.md b/docs/release-control/v6/internal/subsystems/agent-lifecycle.md index e5844a00e..483a9420a 100644 --- a/docs/release-control/v6/internal/subsystems/agent-lifecycle.md +++ b/docs/release-control/v6/internal/subsystems/agent-lifecycle.md @@ -1013,7 +1013,11 @@ class helper. they extract the inner form bodies from the per-type panels and render them inline under the editor while still driving the existing `TrueNASSettingsPanelState` and `VMwareSettingsPanelState` APIs for - save, test, preview, and impact-preview behavior. The add flow + save, test, preview, and impact-preview behavior. Feature-disabled, + delete-error, and probe guidance notices in the connection editor may + compose frontend-primitives' `CalloutCard`; agent-lifecycle owns the + selected-source lifecycle semantics and form handoff, not colored local + notice shells. The add flow must not reintroduce the full per-type workspace (Proxmox discovery card, configured nodes table, node-modal stack; TrueNAS/VMware connection list with headers and row actions) into the credential diff --git a/docs/release-control/v6/internal/subsystems/api-contracts.md b/docs/release-control/v6/internal/subsystems/api-contracts.md index 67fc1862e..663270a5e 100644 --- a/docs/release-control/v6/internal/subsystems/api-contracts.md +++ b/docs/release-control/v6/internal/subsystems/api-contracts.md @@ -406,6 +406,10 @@ payload shape change when the portal presents compact client rows. `frontend-modern/src/components/Settings/AvailabilitySettingsPanel.tsx`, `frontend-modern/src/components/Settings/availabilitySettingsModel.ts`, and `AvailabilityTargetSlot.tsx` own the browser transport shape. + Availability target probe-result and error notices may compose + frontend-primitives' `CalloutCard` for shared settings callout chrome; + API contracts own the target CRUD/test payload semantics and endpoint + routing, not local colored alert shells. Connections ledger rows with type `availability` must route management handoffs, pause, remove, and test actions to those availability-target endpoints and must not reuse node, diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index 476f34425..0a91b52f5 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -1357,6 +1357,10 @@ not a replacement status card, CTA band, or page-local nested card. `frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts` and `frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts`. + Connection-editor status, feature-disabled, delete-error, and probe-result + notices are part of the same settings callout boundary: the editor and + credential slots own the source-specific lifecycle or API meaning, while + `CalloutCard` owns the warning/success/danger shell and compact density. 8. Keep hosted settings-shell framing imports safe for bundle initialization. Self-hosted billing titles, descriptions, and referral copy used by `settingsHeaderMeta.ts`, `settingsNavCatalog.ts`, and adjacent settings @@ -3349,6 +3353,13 @@ maintaining feature-local colored bordered wrappers. The primitive owns the tone palette and the `scale="compact"` density used by smaller settings notices, and the `settings-callout-card-shell` shared-template registry rule requires current settings consumers to compose it instead of reintroducing local panel shells. +Connection-editor status, feature-disabled, delete-error, and probe-result +notices are part of that same settings callout boundary: the editor and +credential slots own the source-specific lifecycle or API meaning, while +`CalloutCard` owns the warning/success/danger shell and compact density. +The `settings-connection-editor-local-*-callout-shell` pattern guards block +future connection-editor files from reintroducing amber, red, or rose local +notice shells. Settings external documentation text links must route through `ExternalTextLink`, while button-styled external actions route through diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json index 343779c14..30b5b4b05 100644 --- a/docs/release-control/v6/internal/subsystems/registry.json +++ b/docs/release-control/v6/internal/subsystems/registry.json @@ -1558,6 +1558,7 @@ "owned_files": [ "frontend-modern/src/components/Settings/APITokenManager.tsx", "frontend-modern/src/components/Settings/apiTokenManagerModel.ts", + "frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx", "frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/NodeCredentialSlot.tsx", "frontend-modern/src/components/Settings/infrastructureOperationsModel.tsx", "frontend-modern/src/components/Settings/NodeModalAuthenticationSection.tsx", @@ -1821,6 +1822,27 @@ "frontend-modern/src/types/api.ts" ] }, + { + "id": "availability-target-settings-client-surface", + "label": "availability target settings client proof", + "match_prefixes": [], + "match_files": [ + "frontend-modern/src/api/availabilityTargets.ts", + "frontend-modern/src/components/Settings/availabilitySettingsModel.ts", + "frontend-modern/src/components/Settings/AvailabilitySettingsPanel.tsx", + "frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx", + "internal/api/availability_handlers.go" + ], + "allow_same_subsystem_tests": false, + "test_prefixes": [], + "exact_files": [ + "frontend-modern/src/api/__tests__/availabilityTargets.test.ts", + "frontend-modern/src/components/Settings/__tests__/AvailabilitySettingsPanel.test.tsx", + "frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts", + "frontend-modern/src/components/Settings/ConnectionEditor/__tests__/AvailabilityTargetSlot.test.tsx", + "internal/api/availability_handlers_test.go" + ] + }, { "id": "frontend-api-clients", "label": "frontend API client proof", diff --git a/frontend-modern/scripts/shared-template-registry.json b/frontend-modern/scripts/shared-template-registry.json index 399fb1b0c..5254d6d2e 100644 --- a/frontend-modern/scripts/shared-template-registry.json +++ b/frontend-modern/scripts/shared-template-registry.json @@ -301,6 +301,13 @@ }, "requiredConsumers": [ { "path": "src/components/Settings/AIProviderConfigurationSection.tsx" }, + { "path": "src/components/Settings/ConnectionEditor/AddressProbeStep.tsx" }, + { + "path": "src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx" + }, + { + "path": "src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx" + }, { "path": "src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx" }, @@ -316,6 +323,35 @@ "path": "src/components/Settings/AIProviderConfigurationSection.tsx", "patterns": ["rounded border border-red-200", "bg-red-50 dark:bg-red-900 px-2 py-1.5"] }, + { + "path": "src/components/Settings/ConnectionEditor/AddressProbeStep.tsx", + "patterns": [ + "rounded-md border border-red-300 bg-red-50", + "rounded-md border border-amber-300 bg-amber-50" + ] + }, + { + "path": "src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx", + "patterns": [ + "border-green-300 bg-green-50", + "rounded-md border border-rose-300 bg-rose-50", + "testToneClass" + ] + }, + { + "path": "src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx", + "patterns": [ + "rounded-md border border-amber-300 bg-amber-50", + "rounded-md border border-rose-300 bg-rose-50" + ] + }, + { + "path": "src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx", + "patterns": [ + "rounded-md border border-amber-300 bg-amber-50", + "rounded-md border border-rose-300 bg-rose-50" + ] + }, { "path": "src/components/Settings/DiagnosticsResultsPanel.tsx", "patterns": [ @@ -2407,6 +2443,72 @@ "scripts/shared-template-audit.mjs" ] }, + { + "id": "settings-connection-editor-local-warning-callout-shell", + "category": "callout", + "summary": "Connection editor settings code must not recreate amber warning callout shells locally; compose CalloutCard compact notices so tone, spacing, and dark-mode styling stay shared.", + "canonical": { + "path": "src/components/shared/CalloutCard.tsx", + "export": "CalloutCard" + }, + "scopes": ["src/components/Settings/ConnectionEditor"], + "extensions": [".tsx"], + "allPatterns": ["rounded-md border", "bg-amber-50"], + "allowedPaths": [], + "ignoredPaths": [ + "src/components/Settings/ConnectionEditor/__tests__/ConnectionEditor.test.tsx", + "src/components/shared/SharedPrimitives.guardrails.test.ts" + ], + "proof": [ + "src/components/shared/SharedPrimitives.guardrails.test.ts", + "src/components/shared/CalloutCard.test.tsx", + "scripts/shared-template-audit.mjs" + ] + }, + { + "id": "settings-connection-editor-local-danger-callout-shell", + "category": "callout", + "summary": "Connection editor settings code must not recreate red or rose danger callout shells locally; compose CalloutCard compact notices so alert tone, spacing, and dark-mode styling stay shared.", + "canonical": { + "path": "src/components/shared/CalloutCard.tsx", + "export": "CalloutCard" + }, + "scopes": ["src/components/Settings/ConnectionEditor"], + "extensions": [".tsx"], + "allPatterns": ["rounded-md border", "bg-rose-50"], + "allowedPaths": [], + "ignoredPaths": [ + "src/components/Settings/ConnectionEditor/__tests__/ConnectionEditor.test.tsx", + "src/components/shared/SharedPrimitives.guardrails.test.ts" + ], + "proof": [ + "src/components/shared/SharedPrimitives.guardrails.test.ts", + "src/components/shared/CalloutCard.test.tsx", + "scripts/shared-template-audit.mjs" + ] + }, + { + "id": "settings-connection-editor-local-red-callout-shell", + "category": "callout", + "summary": "Connection editor settings code must not recreate red danger callout shells locally; compose CalloutCard compact notices so alert tone, spacing, and dark-mode styling stay shared.", + "canonical": { + "path": "src/components/shared/CalloutCard.tsx", + "export": "CalloutCard" + }, + "scopes": ["src/components/Settings/ConnectionEditor"], + "extensions": [".tsx"], + "allPatterns": ["rounded-md border", "bg-red-50"], + "allowedPaths": [], + "ignoredPaths": [ + "src/components/Settings/ConnectionEditor/__tests__/ConnectionEditor.test.tsx", + "src/components/shared/SharedPrimitives.guardrails.test.ts" + ], + "proof": [ + "src/components/shared/SharedPrimitives.guardrails.test.ts", + "src/components/shared/CalloutCard.test.tsx", + "scripts/shared-template-audit.mjs" + ] + }, { "id": "platform-inline-notice-local-amber-shell", "category": "callout", diff --git a/frontend-modern/src/components/Settings/ConnectionEditor/AddressProbeStep.tsx b/frontend-modern/src/components/Settings/ConnectionEditor/AddressProbeStep.tsx index c27b73350..2148c3b97 100644 --- a/frontend-modern/src/components/Settings/ConnectionEditor/AddressProbeStep.tsx +++ b/frontend-modern/src/components/Settings/ConnectionEditor/AddressProbeStep.tsx @@ -1,6 +1,7 @@ import { Component, For, Show } from 'solid-js'; import type { ProbeCandidate } from '@/api/connections'; import { Button } from '@/components/shared/Button'; +import { CalloutCard } from '@/components/shared/CalloutCard'; import { formControl, formField, formHelpText, formLabel } from '@/components/shared/Form'; import { formatConnectionErrorMessage } from '@/utils/connectionErrorPresentation'; import { getInfrastructureAgentHostProfileSupportText } from '@/utils/infrastructureOnboardingPresentation'; @@ -63,41 +64,52 @@ export const AddressProbeStep: Component = (props) => { 0}> -
- {formatConnectionErrorMessage(props.state.errorMessage()) ?? props.state.errorMessage()} -
+
-
-
No supported API-backed platform detected at that address.
-
- - + . + + If this is one of the supported {getInfrastructureAgentHostProfileSupportText()},{' '} + install Pulse Agent instead} > - Choose a source type instead - - . - - If this is one of the supported {getInfrastructureAgentHostProfileSupportText()},{' '} - install Pulse Agent instead} - > - - - . -
-
+ +
+ . + + } + /> 0}> diff --git a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx index c1a476315..405d6460f 100644 --- a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx +++ b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx @@ -1,5 +1,6 @@ import { Component, Show, createSignal, onMount } from 'solid-js'; import { Button } from '@/components/shared/Button'; +import { CalloutCard } from '@/components/shared/CalloutCard'; import { formCheckbox, formControl, @@ -103,11 +104,6 @@ const payloadFromForm = (form: AvailabilityForm): AvailabilityTarget => { }; }; -const testToneClass = (result: AvailabilityTestResponse) => - result.success - ? 'border-green-300 bg-green-50 text-green-800 dark:border-green-900 dark:bg-green-950 dark:text-green-200' - : 'border-rose-300 bg-rose-50 text-rose-800 dark:border-rose-900 dark:bg-rose-950 dark:text-rose-200'; - const presetSensitiveFormKeys: ReadonlySet = new Set([ 'path', 'port', @@ -379,33 +375,41 @@ export const AvailabilityTargetSlot: Component = (p {(result) => ( -
- {result().success - ? `Probe reached the target in ${result().latencyMillis} ms.` - : result().error || 'Probe failed.'} -
+ )}
{(message) => ( - + tone="danger" + scale="compact" + padding="sm" + description={message()} + /> )} {(message) => ( - + tone="danger" + scale="compact" + padding="sm" + description={message()} + /> )} diff --git a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx index 9c7acd48d..74f5e279b 100644 --- a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx +++ b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx @@ -1,5 +1,6 @@ import { Component, Show, createEffect, onMount } from 'solid-js'; import { Button } from '@/components/shared/Button'; +import { CalloutCard } from '@/components/shared/CalloutCard'; import { formCheckbox, formControl, @@ -58,10 +59,15 @@ export const TrueNASCredentialSlot: Component = (pro return (
-
- {props.state.featureDisabledMessage() || - 'TrueNAS connections are disabled for this Pulse tier.'} -
+
@@ -299,12 +305,13 @@ export const TrueNASCredentialSlot: Component = (pro {(message) => ( - + tone="danger" + scale="compact" + padding="sm" + description={message()} + /> )} diff --git a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx index ce92f0316..946978643 100644 --- a/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx +++ b/frontend-modern/src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx @@ -59,10 +59,15 @@ export const VMwareCredentialSlot: Component = (props return (
-
- {props.state.featureDisabledMessage() || - 'VMware connections are disabled for this Pulse tier.'} -
+
@@ -119,9 +124,7 @@ export const VMwareCredentialSlot: Component = (props - props.state.updateForm({ username: event.currentTarget.value }) - } + onInput={(event) => props.state.updateForm({ username: event.currentTarget.value })} placeholder="administrator@vsphere.local" /> @@ -131,9 +134,7 @@ export const VMwareCredentialSlot: Component = (props class={formControl} type="password" value={props.state.form().password} - onInput={(event) => - props.state.updateForm({ password: event.currentTarget.value }) - } + onInput={(event) => props.state.updateForm({ password: event.currentTarget.value })} placeholder={ props.state.form().hasStoredPassword ? 'Saved password retained unless replaced' @@ -169,9 +170,7 @@ export const VMwareCredentialSlot: Component = (props type="checkbox" class={formCheckbox} checked={props.state.form().enabled} - onChange={(event) => - props.state.updateForm({ enabled: event.currentTarget.checked }) - } + onChange={(event) => props.state.updateForm({ enabled: event.currentTarget.checked })} /> Enable this vCenter connection @@ -246,12 +245,13 @@ export const VMwareCredentialSlot: Component = (props {(message) => ( - + tone="danger" + scale="compact" + padding="sm" + description={message()} + /> )} @@ -326,9 +326,7 @@ export const VMwareCredentialSlot: Component = (props variant="outline" size="settingsAction" onClick={() => void props.state.previewCurrentForm()} - disabled={ - props.state.saving() || props.state.testing() || props.state.previewing() - } + disabled={props.state.saving() || props.state.testing() || props.state.previewing()} title="Show the resources Pulse would ingest from this connection without saving or starting polling." > {props.state.previewing() ? 'Previewing…' : 'Preview impact'} diff --git a/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts b/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts index c458fb61c..28e270956 100644 --- a/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts +++ b/frontend-modern/src/components/Settings/__tests__/settingsArchitecture.test.ts @@ -59,6 +59,7 @@ import nodeModalMonitoringSectionSource from '../NodeModalMonitoringSection.tsx? import nodeModalSetupGuideSectionSource from '../NodeModalSetupGuideSection.tsx?raw'; import nodeModalStatusFooterSource from '../NodeModalStatusFooter.tsx?raw'; import nodeModalStateSource from '../useNodeModalState.ts?raw'; +import availabilityTargetSlotSource from '../ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx?raw'; import trueNASCredentialSlotSource from '../ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx?raw'; import vmwareCredentialSlotSource from '../ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx?raw'; import organizationAccessManagementSectionSource from '../OrganizationAccessManagementSection.tsx?raw'; @@ -321,6 +322,9 @@ describe('settings architecture guardrails', () => { reportingPanelSource, securityAuthPanelSource, securityOverviewPanelSource, + addressProbeStepSource, + availabilityTargetSlotSource, + trueNASCredentialSlotSource, vmwareCredentialSlotSource, ]) { expect(source).toContain('CalloutCard'); @@ -329,6 +333,15 @@ describe('settings architecture guardrails', () => { expect(discoverySettingsFormSource).toContain('scale="compact"'); expect(aiProviderConfigurationSectionSource).toContain('scale="compact"'); expect(diagnosticsResultsPanelSource).toContain('scale="compact"'); + for (const source of [ + addressProbeStepSource, + availabilityTargetSlotSource, + trueNASCredentialSlotSource, + vmwareCredentialSlotSource, + ]) { + expect(source).toContain('scale="compact"'); + expect(source).toContain('padding="sm"'); + } expect(discoverySettingsFormSource).not.toContain( 'rounded-md border border-amber-200 bg-amber-50/80', ); @@ -336,6 +349,25 @@ describe('settings architecture guardrails', () => { expect(diagnosticsResultsPanelSource).not.toContain( 'rounded-md border border-amber-200 bg-amber-50', ); + expect(addressProbeStepSource).not.toContain('rounded-md border border-red-300 bg-red-50'); + expect(addressProbeStepSource).not.toContain('rounded-md border border-amber-300 bg-amber-50'); + expect(availabilityTargetSlotSource).not.toContain('testToneClass'); + expect(availabilityTargetSlotSource).not.toContain('border-green-300 bg-green-50'); + expect(availabilityTargetSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); + expect(trueNASCredentialSlotSource).not.toContain( + 'rounded-md border border-amber-300 bg-amber-50', + ); + expect(trueNASCredentialSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); + expect(vmwareCredentialSlotSource).not.toContain( + 'rounded-md border border-amber-300 bg-amber-50', + ); + expect(vmwareCredentialSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); }); it('keeps telemetry disclosure aligned with the security privacy contract', () => { diff --git a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts index 98b7fb88d..ad644db6b 100644 --- a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts +++ b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts @@ -3256,15 +3256,42 @@ describe('shared primitive guardrails', () => { requiredConsumers?: Array<{ path?: string }>; forbiddenPatterns?: Array<{ path?: string; patterns?: string[] }>; }>; + patternGuards?: Array<{ + id: string; + canonical?: { path?: string; export?: string }; + scopes?: string[]; + allPatterns?: string[]; + }>; }; const registeredRule = registry.rules?.find( (rule) => rule.id === 'settings-callout-card-shell', ); + const registeredWarningGuard = registry.patternGuards?.find( + (guard) => guard.id === 'settings-connection-editor-local-warning-callout-shell', + ); + const registeredDangerGuard = registry.patternGuards?.find( + (guard) => guard.id === 'settings-connection-editor-local-danger-callout-shell', + ); + const registeredRedGuard = registry.patternGuards?.find( + (guard) => guard.id === 'settings-connection-editor-local-red-callout-shell', + ); expect(registeredRule?.canonical?.path).toBe('src/components/shared/CalloutCard.tsx'); expect(registeredRule?.canonical?.export).toBe('CalloutCard'); + for (const guard of [registeredWarningGuard, registeredDangerGuard, registeredRedGuard]) { + expect(guard?.canonical?.path).toBe('src/components/shared/CalloutCard.tsx'); + expect(guard?.canonical?.export).toBe('CalloutCard'); + expect(guard?.scopes).toEqual(['src/components/Settings/ConnectionEditor']); + expect(guard?.allPatterns).toContain('rounded-md border'); + } + expect(registeredWarningGuard?.allPatterns).toContain('bg-amber-50'); + expect(registeredDangerGuard?.allPatterns).toContain('bg-rose-50'); + expect(registeredRedGuard?.allPatterns).toContain('bg-red-50'); expect(registeredRule?.requiredConsumers?.map((consumer) => consumer.path)).toEqual([ 'src/components/Settings/AIProviderConfigurationSection.tsx', + 'src/components/Settings/ConnectionEditor/AddressProbeStep.tsx', + 'src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx', + 'src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx', 'src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx', 'src/components/Settings/DiagnosticsResultsPanel.tsx', 'src/components/Settings/DiscoverySettingsForm.tsx', @@ -3279,6 +3306,35 @@ describe('shared primitive guardrails', () => { path: 'src/components/Settings/AIProviderConfigurationSection.tsx', patterns: expect.arrayContaining(['rounded border border-red-200']), }), + expect.objectContaining({ + path: 'src/components/Settings/ConnectionEditor/AddressProbeStep.tsx', + patterns: expect.arrayContaining([ + 'rounded-md border border-red-300 bg-red-50', + 'rounded-md border border-amber-300 bg-amber-50', + ]), + }), + expect.objectContaining({ + path: 'src/components/Settings/ConnectionEditor/CredentialSlots/AvailabilityTargetSlot.tsx', + patterns: expect.arrayContaining([ + 'border-green-300 bg-green-50', + 'rounded-md border border-rose-300 bg-rose-50', + 'testToneClass', + ]), + }), + expect.objectContaining({ + path: 'src/components/Settings/ConnectionEditor/CredentialSlots/TrueNASCredentialSlot.tsx', + patterns: expect.arrayContaining([ + 'rounded-md border border-amber-300 bg-amber-50', + 'rounded-md border border-rose-300 bg-rose-50', + ]), + }), + expect.objectContaining({ + path: 'src/components/Settings/ConnectionEditor/CredentialSlots/VMwareCredentialSlot.tsx', + patterns: expect.arrayContaining([ + 'rounded-md border border-amber-300 bg-amber-50', + 'rounded-md border border-rose-300 bg-rose-50', + ]), + }), expect.objectContaining({ path: 'src/components/Settings/DiagnosticsResultsPanel.tsx', patterns: expect.arrayContaining(['rounded-md border border-amber-200 bg-amber-50']), @@ -3303,11 +3359,42 @@ describe('shared primitive guardrails', () => { reportingPanelSource, securityAuthPanelSource, securityOverviewPanelSource, + addressProbeStepSource, + availabilityTargetSlotSource, + trueNASCredentialSlotSource, vmwareCredentialSlotSource, ]) { expect(source).toContain('CalloutCard'); } + for (const source of [ + addressProbeStepSource, + availabilityTargetSlotSource, + trueNASCredentialSlotSource, + vmwareCredentialSlotSource, + ]) { + expect(source).toContain('scale="compact"'); + expect(source).toContain('padding="sm"'); + } expect(aiProviderConfigurationSectionSource).not.toContain('rounded border border-red-200'); + expect(addressProbeStepSource).not.toContain('rounded-md border border-red-300 bg-red-50'); + expect(addressProbeStepSource).not.toContain('rounded-md border border-amber-300 bg-amber-50'); + expect(availabilityTargetSlotSource).not.toContain('testToneClass'); + expect(availabilityTargetSlotSource).not.toContain('border-green-300 bg-green-50'); + expect(availabilityTargetSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); + expect(trueNASCredentialSlotSource).not.toContain( + 'rounded-md border border-amber-300 bg-amber-50', + ); + expect(trueNASCredentialSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); + expect(vmwareCredentialSlotSource).not.toContain( + 'rounded-md border border-amber-300 bg-amber-50', + ); + expect(vmwareCredentialSlotSource).not.toContain( + 'rounded-md border border-rose-300 bg-rose-50', + ); expect(diagnosticsResultsPanelSource).not.toContain( 'rounded-md border border-amber-200 bg-amber-50', ); diff --git a/scripts/release_control/subsystem_lookup_test.py b/scripts/release_control/subsystem_lookup_test.py index dc7967b1d..cdbeee3da 100644 --- a/scripts/release_control/subsystem_lookup_test.py +++ b/scripts/release_control/subsystem_lookup_test.py @@ -2860,7 +2860,7 @@ class SubsystemLookupTest(unittest.TestCase): { "heading": "## Shared Boundaries", "path": "internal/api/access_control_handlers.go", - "line": 465, + "line": 469, "heading_line": 123, } ],