Skip to content

fix: show the refusals Gmail gave in a shape this client cannot read - #885

Merged
yadava5 merged 2 commits into
mainfrom
fix/an-unrecognised-refusal-is-visible
Sep 7, 2026
Merged

fix: show the refusals Gmail gave in a shape this client cannot read#885
yadava5 merged 2 commits into
mainfrom
fix/an-unrecognised-refusal-is-visible

Conversation

@yadava5

@yadava5 yadava5 commented Sep 7, 2026

Copy link
Copy Markdown
Owner

The backend has counted unrecognised since #862 — of the messages Gmail listed and would not hand over, the share it refused with a reason this client does not recognise. It reaches lib/gmail/types.ts and the generated schema and stops there. Nothing on any screen has ever read it, and types.ts says so in its own docstring.

That is the most load-bearing of the three counts. An ordinary unreadable message is a deletion or a revoked grant and there is nothing to be done about it. An unrecognised refusal means Gmail answered in a shape this client cannot parse — which is exactly how a scan silently shrinks when Google changes an error envelope. The backend counts it so that change is loud; it was loud only as far as the wire.

A subset, so it renders in a parenthetical

MessagePage.unrecognised is documented as "Of unreadable, the share Gmail refused without a reason we recognise", and the batch measurements agree — an unrecognised refusal is also a drop. So it is never added to anything; a second additive count would double-report every message it names.

9 could not be read (4 refused in a way this app doesn't recognise)

Verified in a browser, both arms

/demo/scan mounts the real InboxWorkbench, so this render path is reachable without a session. Driven through the snapshot the component already restores from:

snapshot rendered
unreadable 9, unrecognised 4 … 9 could not be read (4 refused in a way this app doesn't recognise)
unreadable 9, unrecognised 0 … 9 could not be read

The second row is the control: the parenthetical is conditional, and its absence at zero is observed rather than assumed.

No snapshot version bump, deliberately

unrecognised joins the stored shape as optional and is read with ?? 0 — precisely how unreadable was added on 2026-09-04, whose own comment records that v2 snapshots written before that date do not carry it. The "bump the version" rule in SNAPSHOT_KEY's note is about the verdict shape; an older snapshot restores here with a count of zero and renders exactly as it does today.

Gates: tsc --noEmit clean, eslint --max-warnings 0 clean, unit suite 922/922.

What this does not close

#744's remaining item is the live 200-message mine against the owner's real mailbox, which needs production Gmail and is the owner's to run. The backend half was already fixed (#862) and is already tested.

Refs #744.

The backend has counted `unrecognised` since #862 -- of the messages Gmail
listed and would not hand over, the share it refused with a reason this client
does not recognise. It reaches `lib/gmail/types.ts` and the generated schema
and stops there. Nothing on any screen has ever read it, and `types.ts` says so
in its own docstring.

That is the number that matters most of the three. An ordinary unreadable
message is a deletion or a revoked grant and there is nothing to be done about
it. An UNRECOGNISED refusal means Gmail answered in a shape this client cannot
parse, which is exactly how a scan silently shrinks when Google changes an
error envelope. The backend counts it so that change is loud; it was loud only
as far as the wire.

## A SUBSET, so it renders in a parenthetical

`MessagePage.unrecognised` is documented as "Of `unreadable`, the share Gmail
refused without a reason we recognise", and the batch measurements agree --
an unrecognised refusal is also a drop. So it is never added to anything.
Rendering it as a second count would double-report every message it names.

    9 could not be read (4 refused in a way this app doesn't recognise)

## Verified in a browser, both arms

`/demo/scan` mounts the REAL `InboxWorkbench`, so the render path is reachable
without a session. Driving it through the snapshot the component already
restores from:

    unreadable 9, unrecognised 4  ->  "... 9 could not be read (4 refused in a
                                       way this app doesn't recognise)"
    unreadable 9, unrecognised 0  ->  "... 9 could not be read"

The second is the control: the parenthetical is conditional, and its absence at
zero is observed rather than assumed.

## No snapshot version bump

`unrecognised` is added to the stored shape as OPTIONAL and read with `?? 0`,
which is precisely how `unreadable` was added on 2026-09-04 -- the field's own
comment records that v2 snapshots written before that date do not carry it. The
"bump the version" rule in `SNAPSHOT_KEY`'s note is about the VERDICT shape; an
older snapshot restores here with a count of zero and renders exactly as it
does today.

Gates: `tsc --noEmit` clean, `eslint --max-warnings 0` clean, unit suite
922/922.

## What this does not close

#744's remaining item is the live 200-message mine against the owner's real
mailbox, which needs production Gmail and is the owner's to run. The backend
half was already fixed and is already tested.

Refs #744.
@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
jobtracker-web Ready Ready Preview Sep 7, 2026 7:37am UTC

Request Review

@yadava5
yadava5 merged commit 2b1938d into main Sep 7, 2026
12 checks passed
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.

1 participant