178 lines
12 KiB
Markdown
178 lines
12 KiB
Markdown
# Batch 10 Final QA Report
|
||
|
||
**Date:** 2026-05-24
|
||
**Scope:** Final QA pass, README update, build validation, end-to-end regression checklist
|
||
|
||
---
|
||
|
||
## 1. README Update Summary
|
||
|
||
The following changes were made to `README.md` to reflect all refinement-pass improvements:
|
||
|
||
| Section | Change |
|
||
|---------|--------|
|
||
| **Key Features → Reporting** | Updated to mention direct web reporting via `POST /api/content/:cxid/report` in addition to Telegram bot reports. |
|
||
| **Key Features → Native Media Batching** | Added new row documenting native Telegram photo/video/audio/document batching with automatic 1,024-character caption truncation. |
|
||
| **Tech Stack** | Added `reqwest 0.12` entry for server-side report forwarding. |
|
||
| **API Endpoints** | Added `/api/content/:cxid/file/:file_idx/raw` (raw text), `/api/content/:cxid/report` (direct web report), and noted the homepage includes dynamic bot username link + direct web reporting. |
|
||
| **Admin Commands** | Greatly expanded the table from 3 commands to 16 commands, adding `/help`, `/get_id` (with search variants), `/create_submit_forward`, `/show_c_forward`, `/add_blacklist`, `/rm_blacklist`, `/sban`, `/smute`, `/mute`, `/pban`, `/kick`, `/rmute`, `/rban`. Updated `/blacklist_uid` and `/whitelist_uid` to document the **configured admin-group restriction**. |
|
||
| **Review Groups** | Rewrote to document web report flow and inline keyboard actions (`[ Rmv + Ban ]`, `[ Delete Only ]`, `[ Blacklist Only ]`, `[ Ignore ]`). |
|
||
| **Submission Forward System** | **New subsection** documenting the full forward workflow: creation, user submission, review with action buttons, approval media batching, caption truncation, and DM confirmation. |
|
||
| **Auto-Destruct & Password Protection Fixes** | **New subsection** documenting: HEAD requests no longer consume views; `serve_raw_file` now mirrors `serve_file` increment behavior; frontend password UX improvements (field appears on `401`, "Incorrect password." error). |
|
||
|
||
---
|
||
|
||
## 2. Build Results
|
||
|
||
### `cargo check --workspace`
|
||
**Result:** ✅ PASS
|
||
```
|
||
Checking cgcx-content-typing v0.1.0
|
||
Checking cgcx-file-pipeline v0.1.0
|
||
Checking cgcx-server v0.1.0
|
||
Checking cgcx-bot v0.1.0
|
||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.36s
|
||
```
|
||
|
||
### `cargo test --workspace`
|
||
**Result:** ✅ PASS (0 tests; all suites compile and run cleanly)
|
||
```
|
||
Finished `test` profile [unoptimized + debuginfo] target(s) in 21.37s
|
||
All test suites: 0 passed; 0 failed; 0 ignored
|
||
All doc-tests: 0 passed; 0 failed; 0 ignored
|
||
```
|
||
**Note:** Zero unit/integration tests exist across the workspace. All crates compile under test profile.
|
||
|
||
### `cd frontend && npm run build`
|
||
**Result:** ✅ PASS
|
||
```
|
||
vite v8.0.14 building client environment for production...
|
||
✓ 621 modules transformed.
|
||
✓ built in 5.44s
|
||
```
|
||
**Non-blocking warning:** JS chunk >500 kB (pre-existing, not a regression).
|
||
|
||
---
|
||
|
||
## 3. Final End-to-End Regression Checklist (Batches 1–10)
|
||
|
||
### Batch 1 — Command Fixes & View Count Safety
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 1.1 | `/get_id` works in groups, supergroups, and channels (admin-only) | ✅ | `is_admin()` uses `get_chat_member()` + checks `Administrator \| Owner`. Works for all chat types. `handle_get_id_search()` uses `get_chat_administrators()` for search. |
|
||
| 1.2 | `/help` renders without Telegram parse errors | ✅ | Uses `.parse_mode(ParseMode::Html)`. Special chars escaped via `escape_html()`. No unescaped `&`, `<`, or `>`. |
|
||
| 1.3 | `/blacklist_uid` and `/whitelist_uid` show usage when args missing | ✅ | Both handlers check `split_whitespace().nth(1).and_then(parse)` and return usage text on failure. |
|
||
| 1.4 | `/blacklist_uid` and `/whitelist_uid` restricted to admin groups | ✅ | Gated by `ctx.config.groups.admin_group_ids.contains(&chat_id.0) && is_admin(...)`. Requires both configured admin group AND admin status. |
|
||
| 1.5 | Password+auto-destroy content no longer 410s on first GET | ✅ | `serve_file`: views incremented only when `!is_range && !is_conditional && !is_head`. Early 410 happens before password check, so first GET passes. |
|
||
| 1.6 | `serve_raw_file` view increment fix | ✅ | Now accepts `method: Method` parameter. View increment guarded by `if !is_head`. Mirrors `serve_file` cleanup logic. |
|
||
|
||
### Batch 2 — Direct Web Reporting & Frontend Dynamic Links
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 2.1 | `POST /api/content/:cxid/report` endpoint exists | ✅ | `cgcx-server/src/main.rs:349` — `.route("/api/content/:cxid/report", post(report_content))`. |
|
||
| 2.2 | `reqwest` in `cgcx-server/Cargo.toml` | ✅ | `reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }`. |
|
||
| 2.3 | Report handler inserts into DB and forwards to Telegram review groups | ✅ | `report_content()` inserts via `ReportRepo`, then iterates `review_group_ids` and sends `sendMessage` via Bot API. |
|
||
| 2.4 | Frontend uses dynamic `BOT_USERNAME` for bot link | ✅ | `frontend/src/lib/api.js:4` exports `BOT_USERNAME`. `Home.svelte` uses `{BOT_USERNAME}` in main link and report links. |
|
||
| 2.5 | Frontend direct report form calls API instead of Telegram deep link | ✅ | `Home.svelte:22` — `fetch(${API_BASE}/api/content/.../report, {method: 'POST', ...})`. |
|
||
|
||
### Batch 3 — Homepage Password UX
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 3.1 | Password field appears when accessing password-protected content | ✅ | `Home.svelte:submit()` — on `401` with empty password, sets `needsPassword = true`. |
|
||
| 3.2 | Incorrect password shows "Incorrect password." error | ✅ | `Home.svelte:29` — on `401` with non-empty password, sets `error = 'Incorrect password.'`. |
|
||
| 3.3 | Correct password navigates to content view | ✅ | On success, `fetchMetadata` resolves and `popstate` event triggers router navigation. |
|
||
|
||
### Batch 4 — Forward System, Media Batching, Caption Safety
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 4.1 | Review message sent with correct inline keyboard | ✅ | `finalize_upload` sends keyboard with `[ Approve ]`, `[ Ignore ]`, `[ Blackl. ]`, `[ Ban ]`, `[ Ban/BL u. ]`. |
|
||
| 4.2 | `handle_forward_callback` handles all five actions | ✅ | Match arms for `approve`, `ignore`, `blk`, `ban`, `banblk` at lines 1899–2114. |
|
||
| 4.3 | Permission check on review group before action | ✅ | `is_admin_in_chat(bot, ChatId(forward_def.review_group_id), ...)` at line 1898. |
|
||
| 4.4 | Media batching handles >10 files by splitting | ✅ | `decrypted.chunks(10)` in both `finalize_upload` and `handle_forward_callback`. |
|
||
| 4.5 | Video/audio sent as native Telegram types | ✅ | `InputMediaVideo`, `InputMediaAudio` used when `mime_type.starts_with("video/")` / `audio/`. |
|
||
| 4.6 | Caption truncated to 1,024 characters | ✅ | `if caption.chars().count() > 1024 { caption = caption.chars().take(1024).collect(); }` at line 1953. |
|
||
| 4.7 | Approve action sends DM confirmation to submitter | ✅ | `bot.send_message(ChatId(submission.user_id), ...)` with posted link and direct access link. |
|
||
|
||
### Batch 5 — Review Action Buttons
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 5.1 | `[ Approve ]` callback sets password, forwards media, DMs user | ✅ | Lines 1899–2053. Sets direct password hash, forwards media, edits review message to `[ APPROVED ]`. |
|
||
| 5.2 | `[ Ignore ]` callback DMs rejection, edits message | ✅ | Lines 2054–2065. DMs rejection, edits review message to `[ IGNORED ]`. |
|
||
| 5.3 | `[ Blackl. ]` callback adds to forward blacklist | ✅ | Lines 2066–2077. Adds user to forward blacklist, edits to `[ BLACKLISTED ]`. |
|
||
| 5.4 | `[ Ban ]` callback bans in destination + review groups | ✅ | Lines 2078–2094. Bans, inserts punishments, edits to `[ BANNED ]`. |
|
||
| 5.5 | `[ Ban/BL u. ]` callback bans + blacklists | ✅ | Lines 2095–2114. Combines ban and blacklist, edits to `[ BAN/BL ]`. |
|
||
|
||
### Batch 6 — GLOBAL_BAN Propagation
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 6.1 | `GroupsConfig.global_ban: bool` with default `false` | ✅ | `cgcx-config/src/lib.rs:66–73`. |
|
||
| 6.2 | `propagate_punishment()` early returns if `!global_ban` | ✅ | `cgcx-bot/src/main.rs:2270–2272`. |
|
||
| 6.3 | Target chats: admin groups + review groups + active forward destinations | ✅ | Lines 2274–2290. |
|
||
| 6.4 | Bot admin check skips chats where bot is not admin | ✅ | `is_admin(bot, ChatId(chat_id), bot_id).await` before applying. |
|
||
| 6.5 | Punishment commands call `propagate_punishment` | ✅ | `/sban`, `/smute`, `/mute`, `/pban`, `/kick` all call it after local insertion. |
|
||
|
||
### Batch 7 — Author Visibility & Metadata
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 7.1 | Upload options include `show_author` toggle | ✅ | `UploadOptions.show_author: bool`, default `true`. `"v1:opt:toggle_author"` callback flips it. |
|
||
| 7.2 | `show_author` stored in DB | ✅ | Migration `005_show_author.sql` adds `show_author INTEGER NOT NULL DEFAULT 1`. |
|
||
| 7.3 | Author hidden when `show_author=false` | ✅ | Server returns `author: null` when `show_author=false` (`main.rs:~534`). |
|
||
| 7.4 | Metadata displays date, size, author on view page | ✅ | `ViewContent.svelte` shows `created_at`, `total_size`, conditional `author` with Telegram link. |
|
||
|
||
### Batch 8 — Deduplication & Hash Blacklist
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 8.1 | `plaintext_hash` computed during encryption | ✅ | `blake3::Hasher` updated in encryption loop in `cgcx-file-pipeline/src/lib.rs`. |
|
||
| 8.2 | Deduplication lookup before storing | ✅ | `find_active_by_plaintext_hash` checked at line ~103. |
|
||
| 8.3 | Ref count increment on reuse | ✅ | `increment_ref_count(&existing.content_id, existing.file_index)` called. |
|
||
| 8.4 | Hash blacklist blocks re-uploads | ✅ | `HashBlacklistRepo::contains(hash_bytes)` called before dedup (line ~99). Returns `CgcxError::BlockedHash`. |
|
||
| 8.5 | `hash_blacklist` table exists | ✅ | Migration `007_hash_blacklist.sql`. |
|
||
|
||
### Batch 9 — Username Tracking
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 9.1 | Username changes logged to configurable JSON file | ✅ | `UserRepo::ensure_exists` logs when `old_username != new_username` to `uname_changes_path`. |
|
||
| 9.2 | Config path default set | ✅ | `Config.uname_changes_path`, default `"data/uname_changes.json"`. |
|
||
| 9.3 | Called on every interaction | ✅ | Bot calls `ensure_exists` on messages and callbacks with `Some(&ctx.config.uname_changes_path)`. |
|
||
|
||
### Batch 10 — Final QA & Documentation
|
||
|
||
| # | Item | Status | Evidence |
|
||
|---|------|--------|----------|
|
||
| 10.1 | README updated with all refinement-pass changes | ✅ | This document. |
|
||
| 10.2 | `cargo check --workspace` passes | ✅ | 5.36s, zero errors. |
|
||
| 10.3 | `cargo test --workspace` passes | ✅ | All suites compile, zero failures. |
|
||
| 10.4 | `npm run build` passes | ✅ | 5.44s, zero errors. |
|
||
| 10.5 | Final regression checklist prepared | ✅ | This checklist. |
|
||
|
||
---
|
||
|
||
## 4. Blockers / Risks
|
||
|
||
1. **Zero Test Coverage**
|
||
- No unit or integration tests exist in any crate. All verification above is static code review.
|
||
- **Recommendation:** Add integration tests for `FilePipeline::ingest_file`, password flows, and report submission.
|
||
|
||
2. **Memory Usage During Forward/Review**
|
||
- Large files are decrypted entirely into memory (`decrypt_bytes` + `InputFile::memory`) during forward approval and review group posting.
|
||
- **Risk:** OOM on constrained hosts with large uploads (e.g., 100 MB+ videos).
|
||
- **Recommendation:** Consider streaming decryption to temp files and using `InputFile::file(path)`.
|
||
|
||
3. **Chunk Size Warning (Non-blocking)**
|
||
- Frontend build warns about >500 KB JS chunk. Pre-existing, not a regression.
|
||
|
||
---
|
||
|
||
## 5. Summary
|
||
|
||
All requested features across batches 1–10 are **implemented and appear correct** based on static analysis. The workspace compiles cleanly, tests pass (trivially), and the frontend builds successfully. The README now accurately reflects the full feature set. The primary remaining risk is the complete absence of automated tests and potential memory pressure during large-file forward operations.
|