docs(moderator): scope the "structural" claim to what the chain actually covers

Round 4 of the audit ladder. No 🔴, verdict "safe to merge"; all four findings
are prose, and the one with a decision consequence is me over-claiming again.

🟡 The chain makes the three PAGE-LEVEL branches mutually exclusive. It does
nothing about `FeedbackBulkBar` and `FeedbackDetail`, which render their own
`FormState` errors and are not in it — and those are the two surfaces in BOTH
historical instances of this defect. So exclusion against them still rests
entirely on the page comparing `refusalTarget` against 'page' and 'orphan'
EXACTLY, which is what the previous paragraph had already retracted as not
structural. Two paragraphs, one contradicting the other, and the more
general-sounding one was the false one.

Measured in the shipped tree, and re-measured here rather than carried over:
widening the orphan consumer to `!== 'page' && !== 'none'` re-opens the 403
double-render with the suite byte-identical green (991 passing) and svelte-check
0/0. That example replaces an earlier one (`=== 'page'` → `!== 'bar'`) which was
measured before the chain existed and which the chain has since made impossible —
a stale worked example for a warning that is still valid.

🟢 The history sentence was wrong about the shape of the base defect: it was the
filter HINT above the table plus an orphaned refusal below it — two DIFFERENT
messages at once, not one refusal rendered twice.

🟢 The justification for moving the alert refuted itself. It said a refusal below
the fold is silent "for anyone who has scrolled to the rows they selected" — but
those rows are inside the table, so the new position is off screen for exactly
that reader too. It is a lateral trade, better near the top and worse near the
bottom; the gap is narrowed, not closed. Said that way now.

This round swept the SHAPE rather than the reported sites: every claim of the
"structural / cannot / by construction" form in the PR's own additions was
re-read and scoped. Three existed; all three are corrected.

typecheck 0/0, 991 passing, lint clean, no executable line changed.
This commit is contained in:
ZacxDev
2026-09-15 13:18:53 -05:00
parent 04812e6259
commit ce464c8d72
2 changed files with 33 additions and 15 deletions
+18 -7
View File
@@ -113,7 +113,8 @@ export const FEEDBACK_BULK_ACTIONS: ReadonlyArray<{ status: FeedbackStatus; labe
const reports = (n: number) => `${n} report${n === 1 ? '' : 's'}`;
/**
* WHICH surface renders an action failure — exactly one of them, by construction.
* WHICH surface renders an action failure. It NAMES one; whether only one acts on the answer is
* the callers' business, and the paragraphs below are exact about how much of that is enforced.
*
* 🔴 THIS IS A FUNCTION RATHER THAN THREE `$derived` CONDITIONS BECAUSE THE DEFECT CLASS IS
* DOUBLE-RENDERING, AND SEPARATE PREDICATES REGENERATED IT TWICE. First a scope test let a bulk 403
@@ -124,13 +125,23 @@ const reports = (n: number) => `${n} report${n === 1 ? '' : 's'}`;
*
* Returning ONE value removes the AMBIGUITY, and it is worth being exact about what that does and
* does not buy. 🔴 THIS FUNCTION CANNOT ENFORCE THE EXCLUSION — that is the CALLERS' doing, and an
* earlier version of this paragraph claimed otherwise. Measured: changing one consumer's comparison
* from `=== 'page'` to `!== 'bar'` re-opens the exact double-render this exists to close, with the
* whole suite green, because no test crosses the function boundary into `+page.svelte`.
* earlier version of this paragraph claimed otherwise. No test crosses the boundary into
* `+page.svelte`, so a loosened comparison there ships green.
*
* What makes it structural is on the OTHER side: the two page-level consumers are branches of a
* single `{#if}` chain, so at most one renders however their conditions are spelled. This function
* supplies the answer; the chain is what stops two surfaces acting on it.
* 🔴 WHAT IS STRUCTURAL IS NARROWER THAN IT SOUNDS, AND THE SCOPE IS THE WHOLE POINT. The three
* PAGE-LEVEL branches — `pageError`, the orphan alert, the filter hint — are arms of a single
* `{#if}` chain in `+page.svelte`, so at most one of THOSE renders however they are spelled.
*
* 🔴 THE TWO SURFACES IN BOTH HISTORICAL INSTANCES OF THIS DEFECT ARE NOT IN THAT CHAIN.
* `FeedbackBulkBar` and `FeedbackDetail` each render their own `FormState` error, so exclusion
* against them rests ENTIRELY on the page comparing this answer against `'page'` and `'orphan'`
* EXACTLY. Measured in the shipped tree: widening the orphan consumer to
* `!== 'page' && !== 'none'` re-opens the 403 double-render — the bar and the page showing one
* sentence twice — with the whole suite green and `svelte-check` clean. Keep both comparisons exact.
*
* ⚠️ An earlier draft of that example named `=== 'page'` → `!== 'bar'`, measured before the `{#if}`
* chain existed. The chain masks that one now, which is exactly why the example is restated against
* the current tree rather than carried forward.
*
* ⚠️ `bar` has NO consumer. The bar renders its own refusal from its component-local `FormState`
* (`FeedbackBulkBar.svelte`), so that arm exists to DENY the page a refusal the bar is showing, not
@@ -248,11 +248,15 @@
/>
<!--
🔴 ONE CHAIN, AND THAT IS WHAT MAKES THE EXCLUSION STRUCTURAL RATHER THAN MAINTAINED. Both
page-level refusals and the filter hint are branches of a single `{#if}`, so at most one can
render whatever literals the conditions above compare — which two independent `{#if}` blocks
could not promise, and did not: an orphaned bulk refusal used to render here AND below the
table, while this hint fired alongside it.
🔴 ONE CHAIN, SO THESE THREE ARE MUTUALLY EXCLUSIVE WHATEVER THEIR CONDITIONS COMPARE — and
that is ALL it buys. `FeedbackBulkBar` and `FeedbackDetail` render their own `FormState` errors
and are NOT in this chain, so exclusion against them still rests on `refusalTarget` being
compared against `'page'` and `'orphan'` exactly; `feedbackRefusalTarget`'s docstring carries
the measured loosening that re-opens the 403.
What two independent `{#if}` blocks could not promise, and did not: the filter hint used to
render above the table while an orphaned bulk refusal rendered below it — two DIFFERENT
messages at once, not one refusal twice.
The hint is last for the reason it always was: "clear the filters" is the wrong advice when
there is a refusal to show, and `refusalTarget === 'none'` is what says there is not.
@@ -260,9 +264,12 @@
{#if pageError}
<ErrorAlert message={pageError} class="mb-4" />
{:else if orphanedBulkFailure}
<!-- 🔴 ABOVE THE TABLE, not after the pager where this used to sit. It is the whole reason the
bar-gone gap is tolerable: a refusal nine columns of rows below the fold is not "visible,
not silent", it is silent for anyone who has scrolled to the rows they selected. -->
<!-- Above the table, not after the pager where this used to sit — beside the other page-level
refusal rather than a screen away from it.
⚠️ A LATERAL TRADE, NOT A FIX: an operator scrolled down to the rows they selected has the
top of the table off screen too, so this is better for a reader near the top and worse for
one near the bottom. Reaching them wherever they are needs scroll-into-view or a sticky
region — a design change, not a move. The bar-gone gap is narrowed, not closed. -->
<ErrorAlert message={orphanedBulkFailure} class="mb-4" />
{:else if refusalTarget === 'none' && data.open !== null && !data.openVisible}
<p class="mb-4 text-sm text-dark-2">