# Strict-expiry rule (intended semantics, enforced by mdip-agent-kit >= 0.1.3 verifyResponse): # a response MUST expire no later than the challenge it answers: response.validUntil <= challenge.validUntil # equality is ALLOWED (the kit caps a response's expiry at exactly the challenge's validUntil); # one millisecond later is REJECTED. A missing response validUntil is REJECTED when the challenge has one. # Separately, at verify time both must still be in the future (now < validUntil); that needs a clock, not a vector. # Timestamps are ISO-8601 (MDIP writes UTC with ms). Since 0.1.4 they are compared as epoch ms, not strings, # so a missing fractional part or a +00:00 offset still compares correctly; a timestamp with NO zone is rejected. # challenge.validUntil response.validUntil expected 2026-10-26T16:41:19.930Z 2026-10-26T16:41:19.930Z accept equal (mdip-challenge-1/-2 are this case) 2026-10-26T16:41:19.930Z 2026-10-26T16:41:19.929Z accept 1 ms earlier 2026-10-26T16:41:19.930Z 2026-10-19T16:41:19.930Z accept a week earlier 2026-10-26T16:41:19.930Z 2026-10-26T16:41:19.931Z reject 1 ms later 2026-10-26T16:41:19.930Z 2026-10-26T17:41:19.930Z reject 1 h later (keymaster's raw default, uncapped) 2026-10-26T16:41:19.930Z 2027-01-01T00:00:00.000Z reject next year 2026-10-26T16:41:19.930Z - reject response has no validUntil - 2026-10-26T16:41:19.930Z accept challenge has no validUntil (nothing to cap) 2026-10-26T16:41:19.930Z 2026-10-26T16:41:19Z accept response without ms (0.930 s earlier) 2026-10-26T16:41:19.930Z 2026-10-26T16:41:20Z reject response without ms, 70 ms later 2026-10-26T16:41:19.930Z 2026-10-26T09:41:19.930-07:00 accept same instant written with an offset 2026-10-26T16:41:19.930Z 2026-10-26T16:41:19.930 reject response with no timezone (fail closed)