Files
worldmonitor/todos/064-pending-p2-activeCache-nonnull-assertion-nullable-map.md
Elie Habib f783bf2d2d fix(intelligence): analytical frameworks follow-up — P1 security + P2 correctness fixes (#2386)
* fix(intelligence): include framework/systemAppend hash in cache keys (todos 041, 045, 051)

* fix(intelligence): gate framework/systemAppend on server-side PRO check (todo 042)

* fix(skills): exact hostname allowlist + redirect:manual to prevent SSRF (todos 043, 054)

* fix(intelligence): sanitize systemAppend against prompt injection before LLM (todo 044)

* fix(intelligence): use framework field in DeductionPanel, fix InsightsPanel double increment (todos 046, 047)

* fix(intelligence): settings export, hot-path cache, country-brief debounce (todos 048, 049, 050)

* fix(intelligence): i18n, FrameworkSelector note, stripThinkingTags dedup, UUID IDs (todos 052, 055, 056, 057)

- i18n Analysis Frameworks settings section (en + fr locales, replace
  all hardcoded English strings with t() calls)
- FrameworkSelector: replace panelId==='insights' hardcode with note?
  option; both InsightsPanel and DailyMarketBriefPanel pass note
- stripThinkingTags: remove inline duplicate in summarize-article.ts,
  import from _shared/llm; add Strip unterminated comment so tests
  can locate the section
- Replace Date.now() IDs for imported frameworks with crypto.randomUUID()
- Drop 'not supported in phase 1' phrasing to 'not supported'
- test: fix summarize-reasoning Fix 2 suite to read from llm.ts
- test: add premium-check-stub and wire into redis-caching country intel
  brief importPatchedTsModule so test can resolve the new import

* fix(security): address P1 review findings from PR #2386

- premium-check: require `required: true` from validateApiKey so trusted
  browser origins (worldmonitor.app, Vercel previews, localhost) are not
  treated as PRO callers; fixes free-user bypass of framework/systemAppend gate
- llm: replace weak sanitizeSystemAppend with sanitizeForPrompt from
  llm-sanitize.js; all callLlm callers now get model-delimiter and
  control-char stripping, not just phrase blocklist
- get-country-intel-brief: apply sanitizeForPrompt to contextSnapshot
  before injecting into user prompt; fixes unsanitized query-param injection

Closes todos 060, 061, 062 (P1 — blocked merge of #2386).

* chore(todos): mark P1 todos 060-062 complete

* fix(agentskills): address Greptile P2 review comments

- hoist ALLOWED_AGENTSKILLS_HOSTS Set to module scope (was reallocated per-request)
- add res.type === 'opaqueredirect' check alongside the 3xx guard; Edge Runtime
  returns status=0 for opaque redirects so the status range check alone is dead code
2026-03-28 01:10:02 +04:00

1.1 KiB

status, priority, issue_id, tags, dependencies
status priority issue_id tags dependencies
pending p2 064
code-review
typescript
correctness
analytical-frameworks

_activeCache.get(panelId)! non-null assertion on a nullable Map value

Problem Statement

src/services/analysis-framework-store.ts line 148:

if (_activeCache.has(panelId)) return _activeCache.get(panelId)!;

The Map stores AnalysisFramework | null (explicitly set to null to represent "no active framework"). The ! non-null assertion coerces null to AnalysisFramework at the type level, misleading the TypeScript compiler. At runtime it works because callers handle null, but the type assertion is incorrect.

Proposed Solution

if (_activeCache.has(panelId)) return _activeCache.get(panelId) ?? null;

Technical Details

  • File: src/services/analysis-framework-store.ts:148
  • Effort: Trivial | Risk: Low

Acceptance Criteria

  • Non-null assertion removed; ?? null used instead
  • Return type of getActiveFrameworkForPanel remains AnalysisFramework | null

Work Log

  • 2026-03-28: Identified by kieran-typescript-reviewer and architecture-strategist during PR #2386 review