Commit Graph
12 Commits
Author SHA1 Message Date
araharah-executor 6302901f82 test(05-05): Worker no-route-proxy gates RP1+RP2 (D-05)
- RP1: zero /api/route + registerRoute/routeProxy tokens in comment-stripped
  bot/src — the Worker gains no route endpoint, even accidentally (T-05-16)
- RP2: zero @araharah/routing specifiers in bot/src — routing lives in the
  webview bundle only; the Worker imports only @araharah/search
- scans grow with the bot/src tree automatically (the PG-gate pattern)
- TDD note: gates target an already-clean tree, so the RED run is a teeth
  proof — a planted violating file fails both gates; removed, both pass
  (74/0 bot suite green)
2026-10-24 06:03:01 +08:00
araharah-executor 0b8671e9ca test(05-03): add failing guidance-envelope types-only gates (GE1-GE7) (RED)
- GE1 TTL constant === 7200 (~2h, D-06)
- GE2 field freeze: envelope 4 fields / snapshot 6 fields (SessionClaim law)
- GE3 inline snapshot: typed inline, zero snapshotRef tokens in bot/src (D-07)
- GE4 types-only: zero behavior tokens comment-stripped (T-05-08)
- GE5-GE7 negative-space guards: one kv namespace, no Env field, no consumer
  (green by construction — redden only on drift; 05-01 C4/C5/C6 precedent)
2026-10-24 05:08:52 +08:00
araharah-executor 5dcef0e2bb 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
2026-10-24 01:21:10 +08:00
araharah-executor 22fda6d12a fix(03-04): HMAC data-check-string excludes only hash — signature field participates (real clients rejected as tampered; erratum M6) 2026-10-23 01:34:19 +08:00
araharah-executor ecaf242d0e feat(03-01): GEO-02 server half both directions — chat-keyboard fallback + GET /api/location + POST /api/location-fallback (claim-scoped)
- handlers/location-fallback.ts: requestLocationFallback (ReplyKeyboardMarkup request_location:true copy from strings.ts), recordSharedPin, registerLocationFallback (filters message.location, T-03-03)
- strings.ts: awaitingPin/shareLocationButton/pinReceived in en+ms (CS1 parity) — all bot copy stays in strings.ts
- bot.ts: createBot threads env.chat_sessions into the fallback handler; optional client fetch seam for tests; one-caller rule documented
- webhook.ts: GET /api/location relay + POST /api/location-fallback trigger, both resolve chat_id & locale from getClaimByToken CLAIM, never client input (T-03-01/26/27); telegram-send failure is category-only 502 (T-03-28)
- location-pin.test.mjs: LP1–LP14 (TTL contract, range guard, cross-user isolation both routes, locale split); LP12/LP13 patch node-fetch's cached default (grammy's node shim transport), then restore
- CS4 scope untouched (handlers/ not scanned); CS1 parity automatic
2026-10-22 23:33:01 +08:00
araharah-executor 4fbbb0b516 feat(03-01): TTL-only KV location-pin layer under the existing privacy gates (GEO-03, PRIV-02)
- kv/location-pin.ts mirrors sessions.ts shape: writePin/getPin/clearPin, key loc:<chat_id> (chat-scoped, claim-derived — never user-id scoped across keys)
- PIN_TTL_SECONDS=300; writePin is the only write path, expirationTtl on the same line referencing the named constant
- getPin is a defensive read: parse guard + shape guard + |lat|<=90 / |lon|<=180 range guard (V5 Input Validation) — corrupt records return null
- privacy.test.mjs: storageModules now scans kv/location-pin.ts, so PG1 (same-line TTL) and PG2 (no persistence-shaped exports) apply automatically
2026-10-22 23:25:59 +08:00
araharah-executor af691ae40e fix(02-bot-skeleton-initdata-security): WR-03 honest rotate-on-new invariant + best-effort post-mint reconciliation (fold in IN-01b dead branch, IN-01c Phase-4 notes) 2026-10-22 20:21:11 +08:00
araharah-executor 3ea1fdd932 fix(02-bot-skeleton-initdata-security): WR-02 fail-closed /telegram/webhook — unarmed WEBHOOK_SECRET rejects (constant 500, category-only log) before grammY's accept-everything compare 2026-10-22 20:18:34 +08:00
araharah-executor 8995498bff fix(02-bot-skeleton-initdata-security): WR-01 cap /api/session body at 4 KB before JSON split (413, category-only logs) 2026-10-22 20:17:34 +08:00
araharah-executor b4393fbcf3 feat(02-03): strings module + text-only command surface with Malay aliases (D-01..D-05)
- src/i18n/strings.ts: single copy source of truth, en + ms identical
  key-sets, clinical/honest start + privacy copy, pickLocale fallback rule
- /start /mula, /help, /privacy /privasi handlers: plain text replies with
  link previews disabled, zero menu/button surface (D-02, grep-gated)
- createBot(env) factory registers exactly the phase command stack
- scripts/register-commands.mjs: one-time setMyCommands, two scopes
  (default + language_code ms), descriptions derived from helpMenu —
  no inline copy, no future-command stubs (D-03/D-05)
- test/commands.test.mjs: CS1-CS6 gates — locale parity, pickLocale
  matrix, PRIV-01 copy gate vs never-facts + TTL wording, D-02 structural
  grep, D-03 menu gap-freedom, D-04 alias completeness (27 passing)
2026-10-22 11:48:50 +08:00
araharah-executor e9aec5833b feat(02-02): TTL-only KV sessions with rotate-on-new + PRIV-02 storage gates (D-06/D-07/D-08/D-14)
- sessions.ts: mintSession (crypto.randomUUID opaque token, T-02-05), rotate-on-new deletes prior session record via chat pointer (D-07), both puts carry expirationTtl: SESSION_TTL_SECONDS on the call line (PRIV-02)
- SESSION_TTL_SECONDS = 900 pairs the session envelope with the D-13 freshness window
- SessionClaim is exactly D-08: user_id, chat_id, issued_at, language_code — nothing else serializes to storage
- sessions.test.mjs: in-memory KV fake asserting finite expirationTtl on every put; D-08 key-set equality; rotate removes old token; expired-token → null (D-14 class)
- privacy.test.mjs: PG1 same-line expirationTtl source gate (auto-tightens to webhook.ts when plan 03 adds it) + PG2 no persistence-shaped exports
- 18/18 PASS across initdata + sessions + privacy suites; full plan GREEN
2026-10-22 11:43:20 +08:00
araharah-executor fc5001a4eb test(02-01): hand-rolled harness + RED initdata vector suite (D-12, TDD RED)
- bot/test/harness.mjs: zero-dep registry (test(name, fn))
- bot/test/runner.mjs: auto-discovers *.test.mjs, suite-load failure -> FAIL case, exit 0 iff all green
- bot/test/initdata.test.mjs: T1-T7 vector contract signed via node:crypto in-suite
  (T1 known-good, T2 tampered, T3 stale 3600s, T4 boundary 899/901, T5 order-independence,
  T6a-c malformed, T7 RFC-4231 node:crypto independence pin)
- demonstrated RED: 8 FAILs / exit 1 against missing src/security/initdata.ts; GREEN lands in plan 02
2026-10-22 11:38:06 +08:00