# Senior Developer — Follow-up Tasks (Round 2) **Date:** 2026-06-01 **Baseline:** `SENIOR_REPORT_2.md`, verified against the committed code. All six actionable items from `SENIOR_FOLLOWUP.md` check out in the repo: the `scraper_enabled` flag now gates the scraper routes, `TipsService` reads the real `planning_goal` from the workspace, `BreakPeriodUpdate` documents its PUT/full-replacement semantics, rate-limit decorators are on the auth and fetch endpoints, the holiday helper uses the `language="sv"` locale, the CI gate is at 40%, and `conftest` seeds a `child_id`. The backend is in solid shape. Two focused things remain for you. --- ## 1. Wire the tips-engine rule logic — `services/tips_service.py` (main task) 9 of the 12 rules still return `None`. These are the headline domain logic and were senior-owned from the start; they're nuanced enough to warrant your eye, and they're now end-to-end testable since `_build_context` reads the real `planning_goal`. Implement each, with tests, using the predicate helpers in `utils/tip_predicates.py`: | Rule | Key predicate / data | |---|---| | `balance_between_parents` | compare `days_used` across parents | | `preserve_for_age_4` | `analytics_service.get_days_left_at_age_4` | | `use_dubbeldagar_strategically` | scan planned days for same-date overlaps | | `lagsta_niva_coverage` | compare tier usage | | `stretch_time_at_home` | `weekly_intensity` < threshold | | `wrap_weekend_with_vacation` | `monthly` salary + FP spanning a weekend | | `wrap_red_days_with_vacation` | `red_day_clusters_in_range` (Swedish holiday helper) | | `long_break_parent_swap` | match `break_periods` to calendar gaps | | `reserve_for_preschool_planning_days` | `preschool_buffer_needed` | The three already wired (`use_vacation_before_expiry`, `skip_fp_first_12_months`, `sgi_minimum_after_age_1`) are good reference shapes. Honour the documented product intent (see `ARCHITECTURE.md §6` and the project notes): the salary-type condition matters — `wrap_weekend_with_vacation` and the red-day wrap apply to **monthly-salaried only, not hourly**; the first-12-months SGI-protection and the ~5-days/week-after-age-1 rules drive the SGI tips. Tips are advisory, not hard validation. As these land, raise the CI `--cov-fail-under` back up from 40 toward the 90 target (there's already a comment in `ci.yml` to that effect). --- ## 2. Review the frontend ↔ backend integration once the junior wires it (light review, not ownership) The junior is fixing a broken frontend build and wiring the page stubs into a working app (see `JUNIOR_FOLLOWUP_2.md`). Two seams are worth a senior review when they reach them, since they're the riskiest: - **Auth flow** — register/login → JWT handling → `AuthContext` token storage and refresh, and the CORS config in `main.py` matching the real frontend origin. - **Manual parental-leave entry path** — the `FetchDataService` manual path is the standalone fallback that must work without the scraper; confirm the frontend hook (`useParentalLeave`) and the new `getParentalLeave` API client function line up with the backend contract. A read-through and a smoke test (`uv run uvicorn app.main:app --reload` + `npm run dev`, walk create-child → plan-days → view-analytics) is enough; you don't need to own the UI work. --- ## Still deferred (no action now) - **Postgres repository impls** (`repositories_impl/postgres/`) — SQLite serves the MVP; port later by copying the SQLite impls and swapping `aiosqlite` → `asyncpg` (`?` → `$1, $2`). - **FK scraper / BankID** — blocked by the legal/ToS gate; the `scraper_enabled` flag is the activation path once it clears. - **Password reset / email verification** — confirmed post-MVP, tracked via the `TODO` you added.