Files
cg_api_secure-webshare/agent4_batch4.md

167 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Batch 4 QA Report
**Date:** 2026-05-24
**Scope:** Workspace build validation, Telegram API constraint analysis, regression checklist
**Blockers:** None
---
## 1. Build Results
| Check | Result | Details |
|---|---|---|
| `cargo check --workspace` | ✅ PASS | Finished in 5.38s, all crates compile cleanly |
| `cargo test --workspace` | ✅ PASS | All test suites pass (0 unit tests present across crates, all doc-tests pass) |
| `cd frontend && npm run build` | ✅ PASS | Built in 1.44s. Warning: `lib-BKGKj-wr.js` (497 kB) and `index-5C1xoqEL.js` (1,038 kB) exceed 500 kB after minification. This is a Vite chunk-size warning, not a build failure. |
---
## 2. Telegram API Constraint Analysis
### 2.1 Caption Length — ⚠️ FLAGGED
**Location:** `crates/cgcx-bot/src/main.rs`, `handle_forward_callback`, `"approve"` action (~line 1810)
**Code:**
```rust
let caption = format!(
"{}\n\nSubmitted by: {}\nDirect link: <code>{}</code>\nForward link: <code>{}</code>",
escape_html(&forward_def.forward_message),
author_line,
link,
forward_link
);
```
**Analysis:**
- `forward_def.forward_message` is stored as `TEXT NOT NULL DEFAULT ''` in SQLite (`migrations/003_forward_system.sql`). SQLite `TEXT` has no practical length limit.
- The fixed parts of the caption (`Submitted by: …`, `Direct link: …`, `Forward link: …`) add ~60120 characters.
- `author_line` can be up to ~60 characters (escaped username + ID).
- `link` is ~80120 characters (base URL + 12-char CXID + 12-char password).
- `forward_link` is ~70100 characters (`t.me/{bot}?start=submitfwdid{code}`).
- **Telegram API limit for captions:** 1,024 characters.
**Risk:** If an admin sets a `forward_message` longer than ~800 characters, the total caption will exceed 1,024 characters. Telegram will reject the `send_media_group` or `send_message` call with a `Bad Request: MEDIA_CAPTION_TOO_LONG` error. The code does not truncate or validate caption length before sending.
**Recommendation:** Truncate `forward_def.forward_message` to a safe limit (e.g., 700 chars) before interpolating into the caption, or split into a separate text message if the message is long.
---
### 2.2 Media Type Handling — 📋 NOTED
**Locations:**
- `finalize_upload`, review-group media batch (~line 1340)
- `handle_forward_callback`, destination media batch (~line 1850)
**Code:**
```rust
let media = if mime_type.starts_with("image/") {
InputMedia::Photo(InputMediaPhoto::new(input_file))
} else {
InputMedia::Document(InputMediaDocument::new(input_file))
};
```
**Analysis:**
- Images are correctly sent as `InputMediaPhoto`.
- **All non-image files are sent as `InputMediaDocument`**, regardless of MIME type.
**Impact:**
- **Video files** (`video/mp4`, etc.) lose native Telegram playback UI (no inline player, no duration badge, no thumbnail generation).
- **Audio files** (`audio/mpeg`, etc.) lose native audio player UI.
- Telegram treats them as generic documents, which degrades UX in review and destination groups.
**Recommendation:** Map MIME types more precisely:
| MIME prefix | Current | Better |
|---|---|---|
| `image/*` | `InputMediaPhoto` | ✅ Keep |
| `video/*` | `InputMediaDocument` | `InputMediaVideo` |
| `audio/*` | `InputMediaDocument` | `InputMediaAudio` |
| other | `InputMediaDocument` | ✅ Keep |
---
### 2.3 Memory Usage — 📋 NOTED
**Locations:**
- `finalize_upload`, review-group decryption (~line 1320)
- `handle_forward_callback`, destination decryption (~line 1830)
**Code pattern:**
```rust
match cgcx_crypto::decrypt_bytes(&ciphertext, &file.encrypted_key_wrapped, &ctx.master_key) {
Ok(bytes) => decrypted.push((file.mime_type.clone(), bytes)),
...
}
...
let input_file = InputFile::memory(bytes.clone());
```
**Analysis:**
1. `tokio::fs::read(&file.stored_path)` loads the entire encrypted file into memory as `ciphertext`.
2. `decrypt_bytes` decrypts in-memory and returns a new `Vec<u8>` (`bytes`). At this point, two copies of the file exist in RAM (ciphertext + plaintext).
3. `InputFile::memory(bytes.clone())` clones the plaintext bytes again for the `InputMedia` struct. Now three copies may exist transiently.
4. Files are batched in chunks of 10 (`decrypted.chunks(10)`), so up to 10 files are held in memory simultaneously.
**Risk:** For large uploads (e.g., a 100 MB video), this can easily exhaust RAM, especially on constrained hosts or when multiple submissions are processed concurrently. The bot does not stream or chunk-decrypt files.
**Recommendation:** Consider streaming decryption to temporary files and using `InputFile::file(path)` instead of `InputFile::memory(bytes)`. This keeps only one copy on disk instead of multiple copies in RAM.
---
## 3. Regression Checklist — Batch 4
Use this checklist before merging or deploying Batch 4 changes:
### Build & Compile
- [ ] `cargo check --workspace` passes with zero errors
- [ ] `cargo test --workspace` passes (all suites green)
- [ ] `cd frontend && npm run build` produces `dist/` without errors
- [ ] No new compiler warnings introduced in `cgcx-bot`
### Bot Runtime
- [ ] Bot starts successfully and connects to Telegram (`get_me` succeeds)
- [ ] InMemStorage dialogue state machine transitions correctly (Start → TermsPending → MainMenu → UploadStaging → UploadOptions → UploadFinalizing)
- [ ] Service message cleanup works in groups/channels and is silently skipped in private chats
- [ ] Punishment expiration timer revokes bans/mutes after duration elapses
- [ ] Global ban propagation (`propagate_punishment`) only runs when `config.groups.global_ban == true`
### Upload & Submission Flow
- [ ] Staging accepts media, documents, and text up to `max_batch_size`
- [ ] Upload options (destroy, download, password, show_author) toggle correctly
- [ ] `finalize_upload` respects `max_total_batch_bytes` limit
- [ ] Disk-space check (`fs2::available_space`) blocks uploads when temp space < 2× batch size
- [ ] Blocked-hash detection (`CgcxError::BlockedHash`) aborts upload and cleans up
### Forward & Review System
- [ ] `/create_submit_forward` validates bot admin status in both destination and review groups
- [ ] Submission links (`?start=submitfwdid{code}`) work and enforce allow-lists
- [ ] Review message is sent to review group with correct inline keyboard
- [ ] **Approve action sends media batch to destination without `MEDIA_CAPTION_TOO_LONG` error**
- [ ] Approve action sends DM confirmation to submitter with posted link
- [ ] Ignore/Ban/Blacklist/Ban+Blacklist callbacks update review message and submitter correctly
- [ ] **Media batching handles >10 files by splitting into multiple `send_media_group` calls**
### Admin Commands
- [ ] `/reload` refreshes moderation lists
- [ ] `/blacklist_uid`, `/whitelist_uid` update DB and moderation engine
- [ ] `/sban`, `/smute`, `/mute`, `/pban`, `/kick` resolve target user and apply restrictions
- [ ] `/rmute`, `/rban` revoke active punishments
- [ ] `/get_id` returns chat ID or searches admins by username/display name
### Security & Stability
- [ ] Panic hook logs location and message
- [ ] `CatchPanicLayer`-swallowed panics are traceable via logs
- [ ] 8MB thread stack prevents stack overflow during dptree dispatch
---
## 4. Blockers
**No critical blockers.** All builds pass.
**Non-blocking issues identified:**
1. **Caption length risk** — can cause Telegram API rejection on approval; should be mitigated before relying on forward system in production.
2. **Media type mapping** — video/audio UX is degraded; nice-to-have improvement.
3. **Memory usage** — large files may cause OOM during forward review/approval; should be monitored or mitigated for production load.