test(04-03): the four CS landmines + the CR1-CR15 /cari gate suite

- commands.test.mjs: commandSources gains commands/cari.ts; CS4 documents
  the SECOND inline-keyboard carve (venue card allowed, reply keyboard
  still banned in commands/); CS5 menu becomes help/privacy/cari; CS5b's
  future-stub ban narrows to /pergi_ke (reserved for Phase 5, D-01); CS6
  registers cari+search in the alias set
- cari.test.mjs NEW: CR1-CR15 — payload shapes captured through the real
  createBot + fake baseFetch (getMe included), plus source-introspection
  gates with the stripComments helper: venue fields, OPEN URL = configured
  origin + plain slug id, NO-CRYPTO law (D-11), one-message alternates,
  callback_data discipline, honest refusal, 128-char cap, always-answer,
  category-only logging (D-15), bilingual copy, registration script, swap
  semantics, hostile-id drop
- register-commands.mjs: menu list gains cari (two fetch calls unchanged)
- [Rule 1] location-fallback.ts: the message handler now passes non-location
  messages through (next) — it matched EVERY message and silently starved
  all downstream message-stage handlers, so /cari never fired through the
  real factory; caught by the fake-transport suite
- suites: bot 65/65 (15 CR + 9 CS + all prior), web 33/33, search 57/57,
  bot:typecheck green
This commit is contained in:
araharah-executor
2026-10-24 01:21:10 +08:00
parent 13e5073261
commit 5dcef0e2bb
5 changed files with 490 additions and 24 deletions
+4 -4
View File
@@ -21,10 +21,10 @@
* SEARCH (D-01/D-02/D-10/D-11): createBot builds ONE gazetteer SearchSource
* (D-03, backend #1) and shares it between the /cari command surface
* (commands/cari.ts) and the alternates switcher
* (handlers/search-alternate.ts) — a single memoized index. The venue card
* + inline keyboard is the SECOND documented exception to the D-02
* plain-text rule (the first being the GEO-02 reply keyboard above). The
* OPEN button's deep-link origin comes from MINI_APP_URL — a configured
* (handlers/search-alternate.ts) — a single memoized index. The venue
* card's inline-button surface is the SECOND documented exception to the
* D-02 plain-text rule (the first being the GEO-02 reply markup above).
* The OPEN button's deep-link origin comes from MINI_APP_URL — a configured
* public value, never user input; a blank origin omits the button rather
* than guessing.
*/
+5 -3
View File
@@ -58,11 +58,13 @@ export async function recordSharedPin(
/** Register the GEO-02 message handler. Filters on ctx.message?.location
* — Telegram-authenticated updates only (T-03-03), so a fabricated pin
* can never enter KV. */
* can never enter KV. A message WITHOUT a location is passed straight
* through (next) — this handler matches EVERY message, so swallowing
* would starve all downstream message-stage handlers (e.g. /cari). */
export function registerLocationFallback(bot: Bot, kv: LocationPinKv): void {
bot.on("message", async (ctx: Context) => {
bot.on("message", async (ctx, next) => {
const location = ctx.message?.location;
if (!location) return;
if (!location) return next();
const chatId = ctx.chat?.id;
if (chatId === undefined) return;
await recordSharedPin(kv, chatId, location);