Source: PRD-018 SC-2 audit, Type [W1].
template/src/widgets/artifact-filters/ui/Filters.svelte:5-15
let {
kinds = [],
status = [],
kindFilter = $bindable(new Set<string>()),
statusFilter = $bindable(new Set<string>()),
...
} = $props();
The widget exists to filter by kind and status, both of which are discriminated string unions defined in entities/artifact/model/types.ts (ArtifactKind, ArtifactStatus). Typing them as string[] / Set<string> throws away exhaustiveness:
- A
<ToggleGroup type="multiple"> could fire any string and the parent silently accepts it.
- HomePage's
n.kind.toLowerCase() returns string and there's no guard that the lowercased form is one of the canonical kinds.
Fix
- Tighten Filter props:
kinds?: ArtifactKind[]; kindFilter?: Set<ArtifactKind> (analogous for status).
- Either:
- Make
Filters accept the canonical-cased kinds and lowercase only at presentation, OR
- Declare
type LowercaseArtifactKind = Lowercase<ArtifactKind> and use it consistently.
Acceptance
npm run check clean.
- A wrong-cased kind passed to Filters is a compile error.
- Exhaustiveness check on
kindLabel(k) / kindColor(k) lights up if ArtifactKind grows.
Related
- Type-safety [W7] in HomePage breach loop — same exhaustiveness gap, can be fixed in this issue or separately.
Audit traceability
Source: PRD-018 SC-2 audit, Type [W1].
template/src/widgets/artifact-filters/ui/Filters.svelte:5-15The widget exists to filter by kind and status, both of which are discriminated string unions defined in
entities/artifact/model/types.ts(ArtifactKind,ArtifactStatus). Typing them asstring[]/Set<string>throws away exhaustiveness:<ToggleGroup type="multiple">could fire any string and the parent silently accepts it.n.kind.toLowerCase()returnsstringand there's no guard that the lowercased form is one of the canonical kinds.Fix
kinds?: ArtifactKind[]; kindFilter?: Set<ArtifactKind>(analogous for status).Filtersaccept the canonical-cased kinds and lowercase only at presentation, ORtype LowercaseArtifactKind = Lowercase<ArtifactKind>and use it consistently.Acceptance
npm run checkclean.kindLabel(k)/kindColor(k)lights up ifArtifactKindgrows.Related
Audit traceability