docktor — Hardening Tracker

live · updated 2026-07-19 12:23:13 MDT · auto-refreshes every 20s

Harden Marathon — live

branch harden/marathon-2026-07-19 · base 1534ba22 · one commit per fix, splittable · rolling PR ↗

5
fixes landed
1
critical/security
3
privacy/consent
+11
tests added
32%
coverage floor

User & developer impact

What you’ll notice

Visible fixes a beta user experiences directly

  • Weather widget survives partial Open-Meteo datahigh
    The Weather widget no longer goes blank where Open-Meteo omits a value — e.g. polar sunrise/sunset, or precipitation past the forecast horizon. Before, one missing value wiped current + hourly + daily.
    Weather
  • Recently Played shows “X minutes ago” againhigh
    The “X minutes ago” line is back on every Recently Played row. Real Spotify timestamps include milliseconds the app couldn’t parse, so the relative time silently disappeared for everyone.
    Music · Recently Played

Quiet guarantees

Invisible robustness / privacy / security wins

  • Crash reports stop leaking your usernamehigh
    Crash reports sent from the beta no longer expose your Mac username. The old redaction missed bare home-folder paths and could even leak a second username by “bridging” across text.
    Feedback · crash reports
  • Nothing is sent before you’ve seen the disclosurehigh
    A crash that happened before you finished onboarding can no longer be transmitted early. Nothing about a crash leaves your Mac until you’ve actually seen the telemetry disclosure and had the chance to opt out.
    Feedback · telemetry consent
  • Feedback dashboard auth bypass closedcritical
    Your submitted feedback, screenshots, and install ID can no longer be read by a stranger. The ops dashboard trusted a header that anyone could fake on the default deployment.
    Feedback backend (Cloudflare Worker)

Ranked impact log

#FixSeverityUser valueDev valueWhat it means for youWhat it means for the codebaseTestsCommit
1Weather widget survives partial Open-Meteo data
Weather
highHighHighThe Weather widget no longer goes blank where Open-Meteo omits a value — e.g. polar sunrise/sunset, or precipitation past the forecast horizon. Before, one missing value wiped current + hourly + daily.The Open-Meteo Codable arrays (precip / sunrise / sunset / UV) now accept null elements; a null sun event is skipped and a null precip/UV reads as 0. +2 tests including a null-laden decode that threw before the fix.+268a90028
CI (macOS)
2Recently Played shows “X minutes ago” again
Music · Recently Played
highHighMediumThe “X minutes ago” line is back on every Recently Played row. Real Spotify timestamps include milliseconds the app couldn’t parse, so the relative time silently disappeared for everyone.played_at now parses both fractional- and whole-second ISO8601 (with fallback); the new regression test uses a real millisecond payload that would have failed before. Also capped a previously-unbounded 401 retry loop in search().+3 (incl. fractional fixture)0315f65e
CI (macOS)
3Crash reports stop leaking your username
Feedback · crash reports
highHigh (privacy)HighCrash reports sent from the beta no longer expose your Mac username. The old redaction missed bare home-folder paths and could even leak a second username by “bridging” across text.redact() rewritten to match a single username segment (no whitespace/newline bridging), handle no-trailing-slash paths, and preserve the real /Users/Shared folder.+3abd2a5e7
CI (macOS)
4Nothing is sent before you’ve seen the disclosure
Feedback · telemetry consent
highHigh (consent)HighA crash that happened before you finished onboarding can no longer be transmitted early. Nothing about a crash leaves your Mac until you’ve actually seen the telemetry disclosure and had the chance to opt out.CrashReportHarvester now requires the TelemetryConsent watermark AND the opt-out toggle, matching the heartbeat gate. The old code checked only the toggle, so a pre-onboarding report could flush on the next launch.+1 new, 8 adaptedd77e275d
CI (macOS)
5Feedback dashboard auth bypass closed
Feedback backend (Cloudflare Worker)
criticalHigh (PII)CriticalYour submitted feedback, screenshots, and install ID can no longer be read by a stranger. The ops dashboard trusted a header that anyone could fake on the default deployment.isDashboardAuthorized no longer trusts the spoofable Cf-Access-Authenticated-User-Email header unless CF_ACCESS_ENABLED is explicitly set; otherwise it requires the signed session cookie. Fully verified locally.+2 (npm 74/74 green)3cb2c61e
npm 74/74 (local, full)

What’s next — ranked backlog

#Target (surface)User valueSeverityConfCostScoreStatus
1Spotify Recently-Played timestamp parse + bounded search retry (Music) — bare ISO8601DateFormatter drops fractional played_at → "Xm ago" vanishes every rowHighHighHighS78LANDED — 0315f65e
2Worker dashboard auth bypass via spoofable Cf-Access-Authenticated-User-Email (feedback-worker src/index.js:909-917) — any request with that header reads all beta-tester PII; default deploy has no Access app in frontHigh (PII)Critical (security)HighS96LANDED — 3cb2c61e (npm test 74/74, fully verified)
3Crash-report redaction leaks usernames (CrashReportParser.swift:155-159) — regex misses /Users/x w/o trailing slash and greedy-bridges across text/newlines, leaking a second usernameHigh (PII)High (security)HighS90LANDED — abd2a5e7 (build + test-target compile green; full run on CI)
4Crash harvester ignores consent watermark (CrashReportHarvester.swift:68-71) — can transmit a crash summary before onboarding/opt-out (heartbeat gates on both; harvester doesn't)High (consent)High (privacy)HighS88LANDED — d77e275d (build + test-target compile green; full run on CI)
5Weather: non-optional Open-Meteo arrays (WeatherManager.swift:176,200-203) — one null (polar sunrise/sunset, null precip) fails decode → entire forecast blanksHigh (widget dead)HighHighS84LANDED — 68a90028 (build + test-target compile green; full run on CI)
6FeedbackService flushPending re-entrancy (FeedbackService.swift:191-205) — boot + harvest drains overlap → duplicate sends / lost queue itemsMed-HighMedHighM72Planned (seamed async)
7Spotify queue decode fails on podcast episode (SpotifyAPI.swift:44-59) — a podcast in the queue throws → whole "Up Next" blanksMedMedMed-HighM70Planned (decodable test)
8Calendar isVideoConferenceURL substring match (CalendarEventParsing.swift:48-57) — lookalike/redirect URLs classified as meetings and auto-opened at startMedMed (auto-open)HighS68Planned (pure test)
9Lyrics multi-timestamp LRC lines (LyricsService.swift:392,399-406) — compressed chorus tags render raw [mm:ss] text and only highlight onceMedLow-MedMedS60Planned (pure test)
10Lyrics updateCurrentIndex non-monotonic freeze (LyricsService.swift:435-442) — early break freezes highlight after any out-of-order timestampMedLow-MedMedS58Planned (pure test)
11Worker /beta/heartbeat unbounded (src/index.js:222-281) — no rate limit, unbounded install_id + uptime → D1 growth / metric pollution / 64-bit overflowMed (dev)MedHighS56Planned (local test)
12Worker malformed cookie/path → unauth 500 (src/index.js:982-991,66) — decodeURIComponent throws → 500 instead of fail-closed 302; add safeDecodeLow-Med (dev)MedHighS50Planned (local test)
13Calendar meet regex misses hyphenated vanity subdomains + case (CalendarEventParsing.swift:72-79)Low-MedLowHighS48Planned (pure test)
14Worker /submit no idempotency → duplicate rows/blobs/emails on client retry (src/index.js:151-209)Low-MedLow-MedHighM44Planned (local test)

Round log

RoundTargetPlan fileCommitVerifyCyclesFilesNotes
0Assess + prioritize + planthis ledger + spotify-recently-played-timestamp-2026-07-19.mdSeeded from latent-bugs-2026-07-19.md; 4 explore agents verified against current tree; most of snapshot already landed; new backlog built
1Spotify played_at parse + bounded search retryspotify-recently-played-timestamp-2026-07-19.md0315f65eHost build gate + test-target compile GREEN; full test+coverage deferred to CI/VM1SpotifyAPI+Library.swift, SpotifyLibraryFetchTests.swift3 tests added incl. fractional fixture that would have failed pre-fix
2Fresh bug-hunt (4 parallel explore agents)this ledgerBeta-visible seed exhausted; surfaced 14 new targets (security/privacy on top): worker auth bypass, crash-report PII leak, consent gate, Weather null-decode, etc.
2Worker Cf-Access auth-bypass fix(from bug-hunt)3cb2c61enpm test 74/74 GREEN (full gate, local)1feedback-worker/{src/index.js,test/dashboard-auth.test.js,README.md,.dev.vars.example}Bypass closed by default; Access honored only when CF_ACCESS_ENABLED="true"
3Crash-report redaction PII leak fix(from bug-hunt)abd2a5e7Build + test-target compile GREEN; full run on CI1CrashReportParser.swift, CrashReportParserTests.swiftUsername no longer leaks (bare path + whitespace-bridge); /Users/Shared preserved; +3 tests
4Crash harvester consent-watermark gate(from bug-hunt)d77e275dBuild + test-target compile GREEN; full run on CI1CrashReportHarvester.swift, CrashReportHarvesterTests.swiftRequires consent watermark AND opt-out toggle (mirrors heartbeat); +1 new test, 8 adapted
5Weather null-element decode tolerance(from bug-hunt)68a90028Build + test-target compile GREEN; full run on CI1WeatherManager.swift, WeatherModelTests.swift, WeatherManagerTests.swift5 Open-Meteo arrays accept null elements; +2 tests
PRCheckpoint: push + full critical review of PR #147(push)pending reviewgit diff main...HEADEvery-5-fixes gate: review whole PR, fix blockers, check CI

All commits on the branch (newest first)

Generated by the harden-marathon tracker · impact data: .cursor/skills/harden-marathon/landed.json · ledger: .cursor/plans/harden-marathon-2026-07-19.md