Skip to content

The three carried API bugs, resolved โ€‹

  • Outcome: one is real and now filed, two are not real in the current tree. No issue was filed for those two.
  • Why this exists: the three were surfaced by the API mutation runs around 2026-08-21 and carried on the daily agenda on 08-21, 08-23, 08-24, 08-27 and 08-28 without ever being written down. They existed only in a cut-section paragraph, which is how a real bug becomes folklore.
  • Checked: 2026-08-28, against the tree at fix/merchant-portal-988.

1. A ban check that ignores expiry: REAL, filed โ€‹

services/api/auth/src/routes/adminUsers.js:170 reads the raw flag. โ€‹

What makes it durable rather than a transient drift. โ€‹

  • Temp bans are lifted LAZILY, by checkLoginBan when the banned user next tries to sign in. A user who never returns keeps banned: true and an elapsed banExpiresAt forever, so the miscount grows rather than settling.

2. A printable-ASCII-only sanitiser: NOT REAL in this tree โ€‹

Every sanitiser in the services is a DENY-list, not an ASCII allow-list. โ€‹

  • sanitizeDisplayName (services/api/lanterns/src/services/lantern.service.js:103) strips C0 controls and DEL, the zero-width family, and the bidi overrides. Nothing else.
  • Its two mirrors (syncPublicProfile.js, backfill-public-profiles.mjs) carry a byte-identical character set.
  • The other sanitisers in the services (sanitizeTitle in assistant, sanitizeMetadata in forge, sanitizeTierFilters in venues) are also deny-lists or key filters.

Verified by running it, not by reading it. โ€‹

InputOutput
Josรฉ รlvarezunchanged
ๅผ ไผŸunchanged
็”ฐไธญๅคช้ƒŽunchanged
๊น€๋ฏผ์ค€unchanged
Ana ๐ŸŽ‰unchanged
Zoรซ, รœnalunchanged
a name containing a zero-width spacethe zero-width space removed, which is the point of it
  • The current character set has been in place since dc70fda3 (2026-06-11), which predates the mutation runs.

3. A lantern uniqueness guard cleared unconditionally: NOT REAL in this tree โ€‹

The clear is conditional, and the code says why. โ€‹

  • services/api/lanterns/src/services/lantern.service.js:452 reads the guard and deletes it only when guardSnap.data()?.lanternId === lanternId, with a comment naming the failure mode: a guard naming a newer lantern must not be deleted by an extinguish of an older one.
  • The other site that touches the guard, schedule.service.js:370, SETS it inside a transaction that first checks activeLanternGuardHeld, which is the invariant rather than a violation of it.
  • The condition entered at ddcb98a3 (2026-08-17), which also predates the mutation runs.

What this means for the agenda โ€‹

  • The row can be retired. One issue exists, two are verified absent, and the evidence for each is above rather than in a session transcript.
  • Both "not real" findings predate the runs that reported them, so the likeliest reading is that the mutation-run summary was imprecise rather than that something was quietly fixed. Worth knowing before trusting a future summary from the same source without a location.

One thing found while looking, not filed โ€‹

services/api/assistant has no ban check at all. โ€‹

  • grep -rc "isActivelyBanned" services/api/assistant/src returns zero matches, while every other service re-fetches the user and checks it. The service does have a requireAdmin.
  • First noted in the operator's agenda on 2026-08-21 as "pre-existing and out of today's scope, needs its own issue", and it still has none.
  • Not filed here because it was outside what this session was asked to file, and a security gap deserves its own deliberate write-up rather than a rider. Surfaced so it is not lost a second time.

Built with VitePress