Files
cg_api_secure-webshare/AI_MASTER_PLAN.md

10 KiB
Raw Blame History

AI Master Plan — cg.cx Refinement Pass

1. Current Repo Understanding

Architecture

  • 10-crate Rust workspace (cgcx-core, cgcx-config, cgcx-crypto, cgcx-db, cgcx-storage, cgcx-content-typing, cgcx-file-pipeline, cgcx-moderation, cgcx-bot, cgcx-server)
  • SQLite database with WAL mode, 7 migrations already applied (001_init through 007_hash_blacklist)
  • Svelte 5 SPA frontend (frontend/), Vite build, served as static files by Axum fallback
  • Teloxide bot (standalone binary) + Axum server (standalone binary), both share DB and config
  • Content encrypted with XChaCha20-Poly1305, per-file CEKs wrapped with AES-KW under a master key
  • BLAKE3 plaintext hashes stored for deduplication and hash-blacklist enforcement

Already Implemented (verified in code)

Task Status Location
D — GLOBAL_BAN config config/default.toml [groups] global_ban; propagate_punishment() in bot
F — Approval message with media batches handle_forward_callback "approve" — decrypts files, batches up to 10, appends caption to last batch
G — Review group media finalize_upload — decrypts and sends media batches to review group, appends review text to last batch
H — Review buttons (Ban, Blackl., Ban/BL u.) Inline keyboard in finalize_upload and handlers in handle_forward_callback
K — Show/Hide Author toggle UploadOptions.show_author, toggle_author callback, show_author DB column (migration 005)
L — File list metadata ViewContent.svelte shows created_at, total_size, author (username hyperlink + ID)
M — Deduplication FilePipeline::ingest_file checks find_active_by_plaintext_hash, increments ref_count
N — Hash blacklist HashBlacklistRepo, migration 007, blocked-hash rejection in pipeline
O — Username change tracking UserRepo::ensure_exists logs changes to data/uname_changes.json (configurable path in config)
Partial A — Misc report UI Home.svelte already has "Report Content via Telegram" link + "Report Content directly" input/button
Partial Q — Homepage bot link Home.svelte already has t.me/{BOT_USERNAME} link, but in wrong DOM order and styling needs tweak

Actual Bugs / Gaps to Fix

Task Root Cause Fix Strategy
B — /get_id Admin commands gated behind msg.chat.is_group() || msg.chat.is_supergroup(), excluding channels. Also, HTML parse errors in logs come from unescaped <arg> tokens in /help, but /get_id must also be hardened for channels where msg.from / admin visibility differs. Add msg.chat.is_channel() to admin command scope. Ensure handle_get_id_search gracefully handles channels (get_chat_administrators works in channels too if bot is admin).
C — /help help_text raw string contains literal <ID>, <@username>, <displayname>, <user_id>, <dur>, <unit>. Telegram HTML parse mode rejects unsupported tags like <id>. Escape all argument placeholders: replace <arg> with &lt;arg&gt; or [arg]. Minimally invasive: keep the rest of the formatting intact.
E — blacklist_uid / whitelist_uid Commands are technically restricted to admin_group_ids inside the handler, but the outer command dispatch allows them in any group for admins, producing a confusing "only available in admin group" message. Missing-parameter handling exists but UX is inconsistent with other admin commands. Move the admin-group check into the command dispatch so non-admin-group chats get a clear "Unauthorized" response. Ensure missing-parameter usage info is returned before the admin-group gate when possible, so users in the admin group see usage info immediately.
I — Password + auto-destroy 410 serve_file increments view_count for HEAD requests because is_conditional only checks If-None-Match, not request method. Some browsers/proxies/link previews issue HEAD before GET, consuming the view and causing the subsequent GET to hit view_count >= max_views → 410. Add Method extractor to serve_file and skip view increment when method == Method::HEAD. Also skip increment for any non-GET method as defense-in-depth.
J — Password field UX Home.svelte submit() calls fetchMetadata(cxid) without password first. For password-protected content this returns 401, throws, and the catch block sets a raw JSON error string. needsPassword is never set to true, so the password field never appears on the home page. Users cannot access password content from the home page at all. Restructure submit(): on 401 from fetchMetadata, explicitly check if the error is auth-related and set needsPassword = true instead of treating it as a generic error. Ensure password verification only runs on explicit submit/Enter, not on keystrokes.
A — Misc report (complete) Frontend UI exists but the "direct" report still opens a Telegram deep link instead of submitting via the web backend. The hardcoded harmfulmeowbot username is wrong; should use BOT_USERNAME from api.js. Add POST /api/report endpoint to the server (it has access to config.telegram.bot_token). Server inserts report into DB and forwards a notification to configured review groups via direct Bot API HTTP calls. Update frontend to call the API instead of opening Telegram.
Q — Homepage bot link Bot link is present in Home.svelte but DOM order is wrong (currently above Content ID label; should be between Content ID field and "-- cannibal girls --"). Styling says underline + very dark green/blackish green; current color is var(--retro-green) which may need to be var(--retro-accent) or a darker custom value. Reorder elements in Home.svelte. Adjust CSS to match spec. Keep BOT_USERNAME dynamic import.

2. Locked Implementation Rules

  • No broad rewrites. Fix only the targeted bugs and gaps.
  • No redesign of working flows. The upload pipeline, encryption, submission forward system, and moderation engine are working — do not touch them except where task I requires the HEAD-request guard.
  • Preserve existing frontend style and behavior. Keep retro theme, fonts, colors, and animations. Only adjust the specific elements requested in A, J, Q.
  • No cleanup-only changes. Do not refactor unrelated code, rename variables, or change formatting.
  • 4-agent cycle mandatory for implementation batches.
  • SQLite schema is frozen except if a new migration is absolutely required. Tasks AQ do not need new DB tables (report endpoint can reuse existing reports table with reporter_user_id = 0 for web reports).

3. Exact Batch Order for This Refinement Pass

Batch 1: Security + Stability (Agent 1)

  • B — /get_id channel support and robustness
  • C — /help HTML escaping fix
  • E — blacklist_uid/whitelist_uid command behavior refinement
  • I — HEAD request view-count bugfix in serve_file

Batch 2: Telegram Bot + Permissions (Agent 2)

  • Verify Batch 1 bot changes compile and pass basic smoke tests
  • A backend — Add POST /api/report endpoint to server (reuse reports table, forward to Telegram review groups via reqwest HTTP call to Bot API)
  • O verification — Confirm username tracking writes correctly in channels/groups
  • D verification — Confirm global_ban propagation logic works with recent schema

Batch 3: Content Delivery + Rendering (Agent 3)

  • A frontend — Wire "Report Content directly" to call POST /api/report instead of Telegram deep link
  • J — Fix home page password flow (needsPassword trigger on 401)
  • Q — Reorder bot link, adjust underline/dark-green styling
  • L verification — Ensure metadata bar renders correctly after Batch 1 server changes

Batch 4: Docs + QA + Regression (Agent 4)

  • P — Update docs/COMMANDS.md, docs/API.md, docs/MODERATION.md, README.md to reflect all changes
  • Regression test checklist: /get_id in group + channel, /help output, blacklist_uid usage, password+auto-destroy content loads on first GET, home page password flow, report submission API, bot link styling
  • Run cargo check --workspace and cargo test --workspace
  • Run frontend build (cd frontend && npm run build) and verify no new warnings

4. Key Risks

Risk Mitigation
Adding Method extractor to serve_file changes its signature and could break route registration if not matched exactly. Use extract::Method in the handler signature; Axum get() accepts handlers with extra extractors.
POST /api/report needs to send Telegram messages from the server, which currently has no Telegram client. Use reqwest (already transitive via Axum) to make direct HTTPS POSTs to https://api.telegram.org/bot<token>/sendMessage. Add reqwest explicitly to cgcx-server/Cargo.toml.
Channel admin command handling may behave differently because msg.from in channels can be the channel itself or anonymous. Use msg.sender_chat or check msg.from carefully; is_admin still works with the bot's own admin check.
Frontend fetchMetadata 401 handling change in J must not break non-password flows. Only set needsPassword = true when err.status === 401. Keep existing catch behavior for other errors.

5. Exact 4-Agent Loop

Batch N assigned to 4 subagents -> execute in parallel -> wait for all 4 ->
brief review -> update AI_CHECKPOINT.md -> continue to Batch N+1

Agent definitions (always use these exact names):

  1. Security + Stability — Server-side hardening, HTML escaping, view-count logic, command permission gates
  2. Telegram Bot + Permissions — Bot command behavior, channel support, global_ban, backend API wiring
  3. Content Delivery + Rendering — Frontend UX, Svelte components, API integration, styling
  4. Docs + QA + Regression — Documentation updates, end-to-end verification, build checks, regression checklist

6. Resume Rules

  • On any resume, read this file first, then AI_CHECKPOINT.md, then AI_RESUME_PROMPT.md.
  • Do not skip batches. Do not merge batches.
  • If a batch fails review, re-run that batch before advancing.
  • Update AI_CHECKPOINT.md after every batch completes.
  • Preserve all existing working behavior not explicitly listed for change.