mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
Wave-D reconcile report at .planning/phase-D-reconcile-report.md; deferred items seeded to .planning/v1419-backlog.md; strategic v1.5 items appended to .planning/v15-backlog.md from the v1.4.18 Product-Lead review. STATE.md marks Wave D done. Prettier sweep also touched the planning markdown table widths; no content change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
12 KiB
v1.4.16 backlog (deferred from v1.4.15 phase D)
Severity-grouped, file:line, terse. Items here came out of the parallel phase-D code-review / security / design / senior-dev / simplify agents.
HIGH — deferred (correctness / coupling)
code-review (4)
- H1 —
src/app/api/admin/backups/[id]/restore/route.ts:253-377— scrub raw Prisma error in catch block; return stable "Restore failed" 500 + audit row carries verbose text. Admin-only leak, low blast. - H2 —
src/app/api/admin/backups/[id]/restore/route.ts:353-366+src/lib/validations/backup.ts:73-81— tightenmoodEntrySchema.tagstoz.union([z.null(), z.string().refine(JSON.parse → array)])OR validate via JSON-parse in pre-tx loop. - H3 —
src/components/charts/mood-chart.tsx:185-219vs:247-292— exportedaggregateMoodEntriesand inlinechartDataaggregation diverge; unit test exercises a bucketing user never sees. Either drop the export or refactorchartDatato call it. Charts visual style constraint applies — function-extract only, no visual change. - H4 —
src/components/onboarding/tour-launcher.tsx:138-170— scope sessionStorage keys (healthlog-tour-session-dismissed,healthlog-tour-referrer) by user id OR clear on logout. Multi-account / impersonation only.
design / UX (1 of 5 — others fixed)
- H4 design — Button/Tabs/Switch default heights below 44 px on
the new B1/B3/B5 surfaces:
src/components/admin/backups-section.tsx:84,343,397,438,492,src/components/settings/notification-status-card.tsx:264,280,src/components/onboarding/tour.tsx:385,396,405,src/components/admin/recent-audit-preview.tsx:80-83. Cross-cuttingbutton.tsxh-9 → h-11bump, sweep call-sites.
senior-dev (4)
- H1 senior —
src/app/page.tsx(1031 LOC) — split<DashboardShell>+<DashboardTileStrip>+<DashboardChartGrid><DashboardEmptyState>; pull visibility resolver intosrc/lib/dashboard-visibility.ts. Mechanical.
- H2 senior —
src/components/settings/integrations-section.tsx(883 LOC) — split intosrc/components/settings/integrations/{integration-status-banner, withings-card, moodlog-card}.tsx+ composing index. Mirror admin per-section pattern. - H3 senior — Process — adopt
superpowers:using-git-worktreesper parallel agent so commit messages match diffs. Eight v1.4.15 commits had drift.
MEDIUM — deferred
code-review
- M1 —
src/lib/ai/generate-insight.ts:155-158— retry-once injects correction intouserPrompt, notsystemPrompt; either fix the path or fix the docstring. - M2 —
src/lib/ai/codex-client.ts:101-138— documentgetLastDiagnostics()not concurrent-safe OR move intogenerateCompletion()result envelope. - M3 —
src/lib/notifications/channel-state.ts:90-130— collapse the two Prisma writes into one transaction so increment + retry-stamp + audit are atomic. - M4 —
src/lib/notifications/dispatcher.ts:75-97— legacy Telegram migration upsertsenabled: trueon every send; will re-enable channels B3 auto-disabled. Add guard "only when no row exists at all" or stop touchingenabled. - M5 —
src/components/charts/medication-compliance-chart.tsx:75-92— render days wheretaken === 0 && scheduled > 0as missing-data (skip / dashed) instead of 0 %. Charts visual constraint applies — semantic-only, no Dracula change. - M6 —
src/lib/notifications/dispatcher.ts:108-111,src/lib/integrations/status.ts:476-484,src/app/api/internal/deploy-webhook/route.ts:128-141— splitSYSTEM_ALERT_DEPLOY/SYSTEM_ALERT_INTEGRATIONevent types so admins can opt out of one without losing security alerts. - M7 —
src/components/doctor-report/doctor-report-dialog.tsx:64-75, 151-152— anchor date range to Europe/Berlin explicitly OR document the off-by-one boundary risk.
security
- M1 sec —
src/app/api/admin/backups/[id]/restore/route.ts:253-377— pass{ timeout: 30_000, maxWait: 5_000 }toprisma.$transaction(); default 5s trip leaves user partially restored on slow disk / large payload. - M2 sec —
src/app/api/admin/backups/upload/route.ts:193,src/lib/crypto.ts:199— captureextractKeyId(encrypted)inadmin.backups.uploadauditdetailsfor forensic key-rotation trace. - M4 sec —
src/app/api/admin/audit-log/route.ts:34-53— documentdetailsJSON returned cross-tenant, must be tightened before any multi-tenant release. - M5 sec —
src/app/api/admin/notifications/test/route.ts— addcheckRateLimit('admin-notifications-test:' + admin.id, 5, 5min)mirroring user-side test endpoints. - M6 sec —
src/app/api/admin/backups/[id]/download/route.ts:92-114— RFC 5987 filename or drop userId from filename; defensive against future ID-format change. - M7 sec —
src/app/api/admin/backups/[id]/restore/route.ts:259-279— decide + document: restore preserves WithingsConnection, IntegrationStatus, encrypted credentials, Telegram creds. Either extend delete scope to mirrorDELETE /api/admin/dataOR document current preservation behaviour.
design
- M1 design —
src/components/admin/recent-audit-preview.tsx:136-140— show compact verb badge on<sminstead of hiding action label. - M2 design —
src/components/admin/backups-section.tsx:124-141— destructive button disabled-state legibility on dark bg. - M3 design —
src/components/admin/backups-section.tsx:371-410— drag-and-drop affordance on backup upload area. - M4 design —
src/components/onboarding/tour.tsx:307-309+:328-334— define click-flow under spotlight cutout (block clicks OR advance on target click). - M6 design —
src/app/achievements/page.tsx:368-370— visually distinguish category-completed (5/5) from in-progress (2/5) with dracula-green badge or trophy icon. - M7 design —
src/components/gamification/recent-achievements-card.tsx:127-130— empty card needs CTA pointing to first-unlock action. Use<EmptyState size="compact">. - M9 design —
src/components/settings/integrations-section.tsx:158,165notification-status-card.tsx— switch absolute timestamps to relative ("vor 3 Min.") onceuseFormatters().relativeTimehelper exists. Helper itself is also a v1.4.16 task.
senior-dev
- M1 senior — Reliability state-machine duplication
(
src/lib/integrations/status.ts+src/lib/notifications/channel-state.tssrc/lib/notifications/retry-policy.ts); extractsrc/lib/reliability/once a third consumer exists.
- M2 senior —
src/lib/notifications/dispatcher.ts:49-105— delete legacyUser.telegramBotToken/chatIdmigration block + the three deprecated User columns in a v1.4.16 schema migration. Verify via SQL audit first. - M3 senior —
src/components/admin/backups-section.tsx(529 LOC) — extract<TypedConfirmDialog>tosrc/components/admin/_dialogs/,formatBytestosrc/lib/format.ts,download-blobplumbing tosrc/lib/download-blob.ts. - M4 senior —
src/components/onboarding/tour.tsx— extractmeasureTarget+computeTooltipPositiontosrc/lib/onboarding/tour-positioning.tsfor unit-test isolation. - M5 senior —
src/app/api/internal/deploy-webhook/route.ts— unifymeta:{}keys to camelCase (applicationName,deployOutcome); document wire-vs-app boundary. - M6 senior —
src/lib/ai/types.ts(insightResultSchema) +src/lib/ai/schema.ts(aiInsightResponseSchema) — single source of truth, migrate route + UI to strict schema, drop.passthrough(), delete legacy. - M8 senior — Pick one config pattern (lazy env-read vs
module-frozen) across
integrations/status.ts+retry-policy.ts; document in CLAUDE.md.
LOW — deferred
code-review
- L1 —
src/components/onboarding/tour.tsx:188—TOOLTIP_HEIGHT = 220fixed estimate; measure rendered card via ResizeObserver. (H2 fix above gave amax-h-[80vh] overflow-y-autoband-aid for v1.4.15.) - L2 —
src/lib/ai/codex-client.ts:470-475— comment-clarity nit onredactBody()regex (downgraded to nit). - L3 —
src/lib/analytics/bp-in-target.ts:57-78—findClosestDia()O(n²); binary-search after sort. - L4 —
src/lib/ai/codex-client.ts:40-45— dropgpt-4ofromDEFAULT_SLUG_FALLBACK_CHAINOR condition on auth method. - L5 —
src/lib/__tests__/dashboard-layout.test.ts— reclassify the typecheck errors (currently called pre-existing in STATE.md but the file is +119 in this milestone).
design
- M5 design —
src/app/achievements/page.tsx:261,280,294—min-h-34non-standard; switch tomin-h-[8.5rem]ormin-h-36. - M8 design —
src/components/settings/notification-status-card.tsx:202-256— colour disabled-reasontext-destructive, consecutive-failurestext-dracula-orangefor at-a-glance triage. - M10 design —
src/components/onboarding/tour.tsx:337-344— live-region:→,so screen readers don't speak punctuation. - M11 design —
src/components/layout/sidebar-nav.tsx:514— tighten admin-sub-item active match topathname === sectionPath || startsWith(${sectionPath}/).
security
- M3 sec —
src/lib/ai/codex-slug-cache.ts:32-34— document the global cache; add Wide Event annotation on slug-rejection invalidation. - M8 sec —
src/app/api/internal/deploy-webhook/route.ts:84-96— acknowledged trade-off, no change needed.
senior-dev
- L1 senior — Frozen-tuple style inconsistency across charts / retry-policy / dashboard-visibility; document canonical pattern.
- L2 senior —
src/components/onboarding/tour-launcher.tsx:124-130— trim 8-line StrictMode comment. - L3 senior —
src/lib/integrations/status.ts:365-383— writenullon encrypt failure instead of sentinel string. - L4 senior —
RANGE_DAYS = [7,30,90]duplicated acrossmedication-compliance-chart.tsx+health-chart.tsx; extract. - L5 senior —
MOODLOG_LAST_SYNCED_AT+IntegrationStatus.lastSuccessAtduplication; document v1.4.16 cutover. - L6 senior —
src/lib/ai/codex-client.ts:477-483— replace__testnamespace with named exports. - L7 senior — Function-signature consistency (
channel-state.tspositional vsstatus.tsobject-arg-bag). - L8 senior —
src/components/gamification/recent-achievements-card.tsx:56-75— movepickRecentUnlockstosrc/lib/gamification/recent-unlocks.ts; same foraggregateMedicationComplianceinmedication-compliance-chart.tsx.
Simplify — deferred (4 of 6 yes-items not applied autonomously)
- F1 —
src/lib/ai/{generate-insight,schema,mock-client}.ts+prompts/insight-generator.ts— schema-enforcement wrapper wired into tests only. Ship-it call: keep as v1.4.16 scaffolding OR revert. - F2 —
src/lib/ai/codex-client.ts:101-138, 174-178, 192-198, 233-237, 242-246—getLastDiagnostics()+CodexAttemptDiagnosticsread only by tests. Either wire intoannotate()or delete. - F8 —
src/lib/doctor-report-{data,pdf,pdf-core}.ts—period.sinceback-compat shim duplicatesperiod.start. Drop after confirming iOS app does not readsince. - F9 —
src/components/onboarding/tour-launcher.tsx:138-170— deletedecidedForover-engineered guard;showTour === nullalready prevents re-fire. - F12 —
src/lib/ai/mock-client.ts:99-102— dropcallCountgetter; conditional on F1.
Process / meta
- Adopt
superpowers:using-git-worktreesper parallel agent for the v1.4.16 marathon. - Migrate route + UI for AI insights to the strict schema; retire
.passthrough(). - Resolve the dashboard-layout.test.ts typecheck regression (currently
blocking
pnpm typecheck).