Skip to content

follow-up(types): tighten ParsedItem.category invariant at LLM-cache assignment site #3753

Description

@koala73

Surfaced by: /ce-code-review kieran-typescript finding KT-001 on PR #3751
Severity: P3 (gated_auto)

Problem

server/worldmonitor/news/v1/list-feed-digest.ts:941 writes `'category', typeof item.category === 'string' ? item.category : ''` defensively. But `ParsedItem.category` is declared as bare `string` (line 145), so from a strict TS perspective the guard is dead code (the `: ''` branch is unreachable to the checker).

The runtime escape hatch is real — `server/worldmonitor/news/v1/list-feed-digest.ts:664` does `cached.get(key) as { category?: string }` with no validation, then assigns `item.category = hit.category` at lines 693 and 740. So the defensive write at the HSET site partially compensates for an upstream type unsafety.

Asymmetry: the neighboring `'title', item.title` / `'link', item.link` / `'severity', item.level` / `'lang', item.lang` writes have no such guard. Either every string field on ParsedItem needs the same `typeof` defense (treating ParsedItem as untrustworthy), or none do.

Options

(a) Tighten the cache-assignment site at lines 693/740: `if (typeof hit.category === 'string') item.category = hit.category;`. Then `ParsedItem.category: string` actually means what it says, and the HSET write can drop the redundant guard (rely on the declared type).

(b) Keep the HSET defensive write and extend the same `typeof` guard to all string fields. More verbose but more honest about the runtime risk.

Recommendation

(a) is cleaner — types should mean what they say. The cache-assignment site is the right place to enforce the invariant. The HSET guard becomes redundant but harmless; can stay as belt-and-suspenders or be removed in a follow-up cleanup.

Context

🤖 Surfaced by /ce-code-review

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Standard priority, backlog or low urgency work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions