Files
cg_api_secure-webshare/agent4_batch4.md

7.5 KiB
Raw Blame History

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:

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:

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:

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.