diff --git a/docs/superpowers/plans/2026-03-22-architect-remediation.md b/docs/superpowers/plans/2026-03-22-architect-remediation.md new file mode 100644 index 0000000..76f2a6f --- /dev/null +++ b/docs/superpowers/plans/2026-03-22-architect-remediation.md @@ -0,0 +1,432 @@ +# Architect Remediation Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Fix 2 API contract breaks, 1 SSRF redirect vulnerability, and 1 test mock drift issue identified in the architect assessment. + +**Architecture:** Frontend types and components are updated to match backend response shapes. Backend scraper gets a custom reqwest redirect policy with per-hop SSRF validation. A shared test fixtures file prevents future mock drift. + +**Tech Stack:** Rust (reqwest redirect policy, std::net::ToSocketAddrs), SolidJS/TypeScript + +**Spec:** `docs/superpowers/specs/2026-03-22-architect-remediation-design.md` + +--- + +## File Map + +### Modified Files +- `frontend/src/types.ts:122-128` — fix `SynthesisListItem` to match backend +- `frontend/src/pages/Home.tsx:179-192` — use preview fields instead of `sections` +- `frontend/src/api/admin.ts:38-39` — pass `providerName` not `id` +- `frontend/src/pages/admin/RateLimits.tsx:70` — pass `provider_name` to API +- `backend/src/services/scraper.rs:53-65` — custom redirect policy with SSRF checks +- `frontend/src/__tests__/pages/home.test.tsx:24-47` — use shared fixtures + +### New Files +- `frontend/src/__tests__/fixtures.ts` — shared typed test mock data + +--- + +## Task 1: Fix `/syntheses` list contract + +**Files:** +- Modify: `frontend/src/types.ts:122-128` +- Modify: `frontend/src/pages/Home.tsx:179-192` +- Modify: `frontend/src/i18n/fr.ts` (may need new key for preview format) + +- [ ] **Step 1: Update SynthesisListItem type** + +In `frontend/src/types.ts`, replace lines 122-128: + +```typescript +// Before: +export interface SynthesisListItem { + id: string; + week: string; + sections: NewsSection[]; + status: string; + created_at: string; +} + +// After: +export interface SynthesisListItem { + id: string; + week: string; + status: string; + created_at: string; + first_section_title: string | null; + first_section_item_count: number; +} +``` + +- [ ] **Step 2: Run TypeScript to see what breaks** + +Run: `cd frontend && npx tsc --noEmit 2>&1 | head -30` +Expected: errors in `Home.tsx` and test files referencing `synth.sections` + +- [ ] **Step 3: Update Home.tsx card preview** + +Replace lines 179-192 in `frontend/src/pages/Home.tsx`: + +```tsx +{/* Before: accesses synth.sections[0].items */} +{/* After: uses preview metadata from backend */} +
{synth.first_section_title}
++ {t('home.previewCount', { count: String(synth.first_section_item_count) })} +
+