Found while implementing #58 (list invites), which fixed it on the lists side. :feature:documents
still has it.
The bug
CustomerStatus in :core:model maps an unrecognised customerStatus string to UNKNOWN, whose
isSubscriber is false.
:feature:documents's currentUserIsSubscriber() treats that as "not a subscriber" — so if the
server ever returns a status the app does not know (a future subscriber:lifetime, a renamed tier,
anything), a paying owner is locked out of their own invite form without the server ever being
asked. The gate is client-side, so there is no 403 to recover from; the feature simply is not
offered.
The fix
:feature:lists (PR #119) treats UNKNOWN as unreadable rather than as free, and fails
open — the server stays the real gate, which it always was. It has a regression test,
an unrecognised customer status is treated as unknown, not free.
Apply the same one-line change to :feature:documents's currentUserIsSubscriber() and add the
equivalent test.
Worth checking at the same time
Any other client-side subscriber gate in the codebase. :core:materialize (#11) and :feature:ai
(#4) both deliberately fail open already, so they are fine — but a grep for isSubscriber before
closing this would be worthwhile.
Why it was not fixed in #58's PR
Scope — :feature:documents had parallel work in flight at the time.
Found while implementing #58 (list invites), which fixed it on the lists side.
:feature:documentsstill has it.
The bug
CustomerStatusin:core:modelmaps an unrecognisedcustomerStatusstring toUNKNOWN, whoseisSubscriberisfalse.:feature:documents'scurrentUserIsSubscriber()treats that as "not a subscriber" — so if theserver ever returns a status the app does not know (a future
subscriber:lifetime, a renamed tier,anything), a paying owner is locked out of their own invite form without the server ever being
asked. The gate is client-side, so there is no 403 to recover from; the feature simply is not
offered.
The fix
:feature:lists(PR #119) treatsUNKNOWNas unreadable rather than as free, and failsopen — the server stays the real gate, which it always was. It has a regression test,
an unrecognised customer status is treated as unknown, not free.Apply the same one-line change to
:feature:documents'scurrentUserIsSubscriber()and add theequivalent test.
Worth checking at the same time
Any other client-side subscriber gate in the codebase.
:core:materialize(#11) and:feature:ai(#4) both deliberately fail open already, so they are fine — but a grep for
isSubscriberbeforeclosing this would be worthwhile.
Why it was not fixed in #58's PR
Scope —
:feature:documentshad parallel work in flight at the time.