# 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 UTC with milliseconds (what MDIP writes), so a plain string compare is exact.
# 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)
