Fail closed on legacy Patrol run snapshots

This commit is contained in:
rcourtman 2026-03-25 22:53:14 +00:00
parent 51884f006e
commit 1c3bd34692
3 changed files with 30 additions and 2 deletions

View file

@ -264,6 +264,10 @@ That same scoped count model must drive conditional findings filters too. The
logic that returns the operator to `Active` when a bucket disappears must all
read from the same snapshot-aware count source rather than mixing
snapshot-scoped pills with global queue truth.
That same fail-closed snapshot rule applies to inline run-history findings as
well. Expanded run cards may render inline findings only when the run carries
an explicit `finding_ids` snapshot; legacy runs without snapshot ids must stay
unknown rather than being coerced into an empty findings snapshot.
That same findings surface should keep its section chrome functional rather
than promotional. Inside the Patrol findings tab, the selected tab already
names the surface, so the findings card should not add another in-card product

View file

@ -433,7 +433,7 @@ export function RunHistoryEntry(props: RunHistoryEntryProps) {
<Show when={run.finding_ids !== undefined}>
<div class="mt-3 pt-3 border-t border-blue-200 dark:border-blue-800">
<FindingsPanel
filterFindingIds={run.finding_ids ?? []}
filterFindingIds={run.finding_ids}
filterOverride="all"
scopeResourceIds={canonicalScopeResourceIds}
scopeResourceTypes={run.scope_resource_types}

View file

@ -116,6 +116,25 @@ describe('RunHistoryEntry', () => {
});
});
it('fails closed for legacy runs without snapshot finding ids', () => {
render(() => (
<RunHistoryEntry
run={{
...run,
id: 'run-missing-finding-ids',
finding_ids: undefined,
}}
isLive={false}
patrolStream={patrolStream}
selected={true}
onSelect={vi.fn()}
/>
));
expect(screen.queryByTestId('findings-panel')).not.toBeInTheDocument();
expect(findingsPanelState.latestProps).toBeNull();
});
it('uses a shared coverage summary when a scoped run checked fewer resources than its scope', () => {
render(() => (
<RunHistoryEntry
@ -149,6 +168,8 @@ describe('RunHistoryEntry', () => {
(element.textContent?.includes('Patrol completed with issues requiring review.') ??
false),
),
).toBeInTheDocument();
});
it('keeps zero-coverage scoped runs on the shared coverage narrative', () => {
render(() => (
@ -176,8 +197,11 @@ describe('RunHistoryEntry', () => {
element?.tagName === 'P' &&
(element.textContent?.includes('Checked 0 of 2 scoped resources') ?? false) &&
(element.textContent?.includes('453ms') ?? false) &&
(element.textContent?.includes('Patrol completed with issues requiring review.') ?? false),
(element.textContent?.includes('Patrol completed with issues requiring review.') ??
false),
),
).toBeInTheDocument();
expect(screen.queryByText(/^Patrol completed in 453ms/)).not.toBeInTheDocument();
});
it('does not claim all clear when the run still had existing issues', () => {