Files
cg_api_secure-webshare/agent2_batch2.md

133 lines
5.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.
# Bot-Side Report Handling Compatibility Assessment (Batch 2)
## 1. Bot Report Format Details
**Location:** `crates/cgcx-bot/src/main.rs:1720-1730`
The bot constructs the forwarded report message as follows (HTML parse mode):
```html
<b>[ NEW REPORT ]</b> #{report_id}
CXID: <code>{cxid}</code>
Reporter: <code>{reporter_id}</code>
Owner: <code>{content.user_id}</code>
Uploaded: <i>{YYYY-MM-DD HH:MM}</i>
Files: <b>1</b>
```
**Notes:**
- `report_id` is the auto-incremented SQLite row ID returned by `ReportRepo::insert`.
- `cxid` is extracted from the users message via `extract_cxid(text)`.
- `reporter_id` is the Telegram `user_id` of the person reporting.
- `content.user_id` is the owner/uploader of the reported content.
- `Files: <b>1</b>` is **hardcoded** to `1` regardless of actual file count.
---
## 2. Inline Keyboard Layout Details
**Location:** `crates/cgcx-bot/src/main.rs:1732-1742`
The inline keyboard is a 2×2 grid:
| Row | Button Label | Callback Data |
|-----|--------------|---------------|
| 1 | `[ Rmv + Ban ]` | `v1:admin:delblk:{report_id}` |
| 1 | `[ Delete Only ]` | `v1:admin:del:{report_id}` |
| 2 | `[ Blacklist Only ]` | `v1:admin:blk:{report_id}` |
| 2 | `[ Ignore ]` | `v1:admin:ign:{report_id}` |
These callbacks are handled by `handle_admin_callback` (`main.rs:1745`), which:
- Validates the user is an admin in the review group chat.
- Looks up the `Report` by `report_id`.
- Performs the requested moderation action and resolves the report.
---
## 3. `ReportRepo::insert` Signature & Behavior
**Location:** `crates/cgcx-db/src/repos.rs:426-433`
```rust
pub async fn insert(
&self,
content_id: &ContentId,
reporter_user_id: i64,
reason: &str,
) -> Result<i64> {
let conn = self.conn.lock().await;
conn.execute(
"INSERT INTO reports (content_id, reporter_user_id, reason) VALUES (?1, ?2, ?3)",
params![content_id.as_str(), reporter_user_id, reason],
)?;
Ok(conn.last_insert_rowid())
}
```
- Returns `last_insert_rowid()` (the generated `report_id`).
- No additional validation inside the repo; the caller is responsible for ensuring `content_id` exists.
---
## 4. Compatibility Assessment for Web Reports (`reporter_user_id = 0`)
### ❌ Critical Issue: Foreign Key Constraint Violation
**Schema:** `migrations/001_init.sql:39-50`
```sql
CREATE TABLE reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content_id TEXT NOT NULL REFERENCES contents(id),
reporter_user_id INTEGER NOT NULL REFERENCES users(id),
reason TEXT NOT NULL,
...
);
```
**Foreign key enforcement is enabled:**
- `cgcx-db/src/lib.rs:21` and `:33` both execute `PRAGMA foreign_keys = ON;`.
**Impact:**
- Passing `reporter_user_id = 0` to `ReportRepo::insert` will **fail with a foreign key constraint violation** because there is no user row with `id = 0`.
- There is **no anonymous/web user seed** or special-case handling anywhere in the codebase.
### ⚠️ Secondary Issue: Reason Field Semantics
**Location:** `crates/cgcx-bot/src/main.rs:1719`
```rust
let report_id = report_repo.insert(&content_id, reporter_id, text).await?;
```
- In the bot flow, `text` is the raw user message (a cxid or share link). The bot stores this raw cxid/link as the `reason`.
- A web report API would naturally accept separate `cxid` and `reason` fields. If the server replicates the bot behavior by passing the cxid as the reason, the database will contain a machine ID instead of a human-readable report reason.
- **Recommendation:** The server should pass the user-supplied human reason (or a placeholder like `"Web report"`) to `ReportRepo::insert`, not the cxid.
### ⚠️ Tertiary Issue: Reporter Display
- The report message displays `Reporter: <code>{reporter_id}</code>`. If `reporter_id = 0`, moderators will see `Reporter: <code>0</code>`, which is indistinguishable from a real user and not user-friendly.
- **Recommendation:** Consider creating a dedicated anonymous/web reporter user (e.g., `id = 0` or a negative sentinel) with a recognizable username, or adjust the report template to show `"Web"` / `"Anonymous"` when the reporter is not a Telegram user.
---
## 5. Recommendations
1. **Create an anonymous/web reporter user row** (e.g., `id = 0` or a dedicated negative ID) in the `users` table before any web report can be inserted, **OR** relax the `NOT NULL` / foreign-key constraint on `reporter_user_id` (requires migration).
2. **Update the server-side report endpoint** to accept a separate `reason` field and pass it to `ReportRepo::insert`, rather than mirroring the bots cxid-as-reason behavior.
3. **Align the report message template** for web reports so that the `Reporter:` line is meaningful (e.g., `"Reporter: Web"` or `"Reporter: Anonymous"`) instead of a raw numeric `0`.
4. **Optional:** Fix the hardcoded `Files: <b>1</b>` in the bot template to use the actual file count from `ContentFileRepo::list_by_content`, so the server report and bot report are consistent.
---
## 6. Summary Table
| Aspect | Bot Behavior | Web Report Compatibility | Risk |
|--------|--------------|--------------------------|------|
| Message format | HTML with hardcoded `Files: 1` | Server can replicate easily | Low (cosmetic) |
| Keyboard layout | 2×2 grid with `v1:admin:*:{id}` | Fully compatible | None |
| `ReportRepo::insert` | Accepts any `i64` for `reporter_user_id` | **Fails at runtime for `0`** | **High** |
| `reason` field | Stores raw cxid/link | Misleading if replicated verbatim | Medium |
| Reporter display | Raw numeric ID | `0` is uninformative | Low |