docs: generate + verify project documentation — canonical docs, per-package READMEs, verified fix pass

- New: docs/ARCHITECTURE.md, docs/GETTING-STARTED.md, docs/DEVELOPMENT.md,
  docs/TESTING.md, docs/CONFIGURATION.md (colored mermaid diagrams, quoted labels)
- Regenerated README.md (arah² / arah2bot naming, canonical clone URL)
- New per-package READMEs: theme/, bot/, web/
- Verified 13 docs against the live codebase (2 fix iterations + 2 residual
  corrections); corrected 56 stale claims across AGENTS/DESIGN/IDEAS/GSD_FIX
This commit is contained in:
araharah-executor
2026-10-23 20:56:40 +08:00
parent af3edefbc6
commit 91ad0c9d93
12 changed files with 103 additions and 70 deletions
+2 -2
View File
@@ -162,7 +162,7 @@ Run from the repo root (`npm run bot:<script>`) or inside `bot/`.
| `npm run typecheck` | `tsc --noEmit` against `src/` with Workers types. |
| `npm run dev` | `wrangler dev --port 8787 --local`. |
| `npm run deploy` | `wrangler deploy` followed by `scripts/set-webhook.mjs`. |
| `npm run commands` | `scripts/register-commands.mjs` — one-time `setMyCommands` in the default and `ms` scopes. |
| `npm run commands` | `scripts/register-commands.mjs` — one-time `setMyCommands` in the default scope, plus a `language_code: "ms"` variant of that same default scope (both calls send `bot_command_scope: { type: "default" }`). |
`scripts/set-menu-button.mjs` is run directly (`node scripts/set-menu-button.mjs`) rather than through a package script; it points the bot's menu button at a `web_app` URL derived from `WEBHOOK_URL`'s origin.
@@ -229,7 +229,7 @@ Session TTL is deliberately tied to the 900 s initData freshness window: a sessi
### initData validation
`validateInitData(raw, botToken, opts?)` parses the Telegram-style querystring manually — values are decoded once and `+` stays literal, so `URLSearchParams` is deliberately not used. The data-check string excludes **only** `hash` (the `signature` field participates; excluding it broke real webviews), sorts by field name, and joins with newlines. The key is derived with `HMAC-SHA256(key="WebAppData", message=botToken)` and compared in constant time. `auth_date` older than `maxAgeSeconds` (default 900) is `stale`; `nowSeconds` is injectable so freshness boundaries are testable at 899/900/901 s.
`validateInitData(raw, botToken, opts?)` parses the Telegram-style querystring manually — values are decoded once and `+` stays literal, so `URLSearchParams` is deliberately not used. The data-check string excludes **only** `hash` (the `signature` field participates; excluding it broke real webviews), sorts by field name, and joins with newlines. The key is derived with `HMAC-SHA256(key="WebAppData", message=botToken)` and compared in constant time. `auth_date` older than `maxAgeSeconds` (default 900) is `stale`; `nowSeconds` is injectable, and the suite covers the boundary at 899 s (ok) and 901 s (stale) — the 900 s boundary itself is not asserted by any case.
---