Problem/Motivation
GrantInventory::revokeJti() marks a grant as spent by writing a redemption counter that expires. When the caller sends no ttl, the mark lasts DEFAULT_KILL_TTL, 30 days. It also removes the grant from the inventory, so the grant no longer appears in the list.
A grant can live longer than that. If its expiry is more than 30 days away, the kill mark expires first. The redemption counter starts again from zero and the signed URL can be redeemed until the grant's own expiry. The revoke returned success, the grant is gone from the operator's list, and nothing shows it came back.
The bulk revoke path uses the same default.
Steps to reproduce
- Configure a gated field with a usage limit and a time to live above 30 days, and mint a grant.
- Revoke the grant by id without a
ttl. - Read the expiry stored for the redemption counter: it is 30 days out, before the grant's expiry.
Found by reading 1.x. The expiry arithmetic is reproduced in a kernel test; redemption after the mark lapses has not been exercised end to end.
Proposed resolution
- In
revokeJti(), read the grant's stored expiry and keep the kill mark until at least that time plus a margin. A caller-suppliedttlmay extend the mark and may not shorten it below the grant's remaining life. - Apply the same rule to bulk revoke.
- When the inventory has no record of the grant, keep today's default.
Remaining tasks
- Kernel tests: a 90-day grant revoked with no ttl and with a short ttl keeps a mark past its expiry; a grant past the mark cannot be redeemed; bulk revoke behaves the same.
- Document the rule in the revoke section of the README.
API changes
None. A short ttl on revoke is raised to the grant's remaining life.
Comments
Comment #2
jmcerdaCommitted to 1.x; ships in 1.10.0. Reproduced end to end with a real mint, revoke and download and a movable clock: before the fix a grant with a 90-day life was served again once the 30-day mark had expired. The kill mark now lasts until the stored expiry of the grant plus one hour. A caller
ttlcan lengthen the mark and cannot shorten it. A grant the inventory does not know keeps the 30-day default. Bulk revoke uses the same rule. Review found a second case: a repeat revoke with a shortttloverwrote the long mark, because the first revoke had already removed the inventory row. Each mark now records its own expiry, so a later revoke cannot shorten it.