Skip to content

fix(magic-link): make consume work on node-redis and tolerate a null consumedAt - #30

Merged
ExorTek merged 1 commit into
fix/shared-redis-dialectfrom
fix/magic-link-consume
Aug 6, 2026
Merged

fix(magic-link): make consume work on node-redis and tolerate a null consumedAt#30
ExorTek merged 1 commit into
fix/shared-redis-dialectfrom
fix/magic-link-consume

Conversation

@ExorTek

@ExorTek ExorTek commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Stacked on #29.

Two independent defects in the same script.

1. node-redis. consume and revokeByEmail passed their Lua arguments in the ioredis positional form for every client, so both failed there. The module header claimed the store was verified against node-redis and @upstash/redis; that claim is corrected to describe what is actually covered.

2. Every client. The script guarded with if record.consumedAt then, and Redis's cjson decodes a JSON null to a truthy sentinel. A record stored with an explicit consumedAt: null therefore read as already consumed and could never be redeemed:

put({...})                    → consume() === true
put({..., consumedAt: null})  → consume() === false   (permanently)

create() omits the field, so the default flow was unaffected — but consumedAt is part of the documented record shape, and normalising an absent field to null is a common round-trip. The guard now excludes cjson.null, as the jwt store's script already did.

Copilot AI lite review requested due to automatic review settings August 6, 2026 09:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…consumedAt

Two independent defects in the same script.

`consume` and `revokeByEmail` passed their Lua arguments in the ioredis
positional form for every client, so both failed against node-redis. The
module header meanwhile claimed the store was verified against node-redis and
@upstash/redis; that claim is corrected to describe what is actually covered.

The script also guarded with `if record.consumedAt then`, and Redis's cjson
decodes a JSON null to a truthy sentinel — so a record stored with an explicit
`consumedAt: null` read as already consumed and could never be redeemed. The
default `create()` path omits the field and was unaffected, but the field is
part of the documented record shape. The guard now excludes cjson.null, the
same way the jwt store's script already did.

The fake client in the unit suite declares itself ioredis-shaped, since the
store now keys on that rather than guessing.
@ExorTek
ExorTek force-pushed the fix/magic-link-consume branch from 4943e97 to 5a2dd7f Compare August 6, 2026 09:17
@ExorTek
ExorTek merged commit 99962b6 into master Aug 6, 2026
3 checks passed
@ExorTek
ExorTek deleted the fix/magic-link-consume branch August 6, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants