== Query parameter extraction == PASS scalar token extracted PASS array-valued token[] rejected as null PASS missing key returns null PASS array-valued token never reaches token validator == Token and base validation == PASS valid token accepted PASS short token rejected PASS token with space rejected PASS token with slash rejected PASS 129-char token rejected PASS 128-char token accepted PASS valid base business PASS unknown base rejected PASS empty base rejected == Exact ICS URL construction == PASS exact export URL PASS invalid token throws in URL builder == Legacy ICS URL validation == PASS valid legacy URL accepted PASS http scheme rejected PASS credentials rejected PASS custom port rejected PASS unknown host rejected (redirect target) PASS wrong path rejected PASS extra query rejected PASS missing export query rejected PASS fragment rejected == Strict date parsing == PASS date-only parsed as all-day PASS date-only starts at midnight PASS invalid Feb 31 is a controlled failure (null) PASS unspecified time does not inherit server clock == Escaped text, unfolding, duplicate properties == PASS calendar name de-identified PASS escaped comma+semicolon decoded PASS escaped backslash decoded PASS no literal backslash-n remains PASS folded line unfolded PASS duplicate SUMMARY collapses to a string == Visible range end (final Sunday 23:59:59) == PASS Feb 2026 range ends 23:59:59 on final Sunday PASS timed event late on final Sunday is included == Stable within-day ordering == PASS order = all-day, 09:00 by title, 14:00 == Timezone handling == PASS UTC 23:30Z crosses to Jan 2 in Perth PASS all-day 2026-02-15 not shifted (Perth) PASS all-day 2026-02-15 not shifted (Sydney) PASS Sydney DST-fallback event lands on 2026-04-05 PASS Perth event shows 09:00 local in Perth == Recurrence == PASS weekly honours EXDATE (02-11 removed) and RDATE (02-20 added) PASS daily COUNT=3 PASS monthly on the 31st SKIPS Feb/Apr (no clamp) PASS monthly never clamps to Feb 28 PASS monthly never produces a March-2 overflow PASS Sydney daily keeps 09:00 wall-clock across DST == Event limit (no silent truncation) == PASS default max-events helper honours the env override PASS calendar below the limit parses completely PASS calendar exactly at the limit parses completely PASS calendar above the limit throws too_large PASS parser returns no partial result when over the limit PASS 5001-event calendar parses completely (no silent 5000 cut) == Cache separation and atomic generation == PASS cache key varies by base PASS cache key varies by token PASS cache key is a sha-256 hex PASS cache available under temp dir PASS cache put ok PASS cache round-trips content PASS different base is a separate entry PASS atomic write leaves no temp files PASS corrupt entry rejected as a miss PASS negative entry stored + read All calendar-data self-tests passed.