2026-01-22 20:21:18 -03:00
|
|
|
# BotApp Development Guide
|
2025-12-04 12:30:05 -03:00
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
**Version:** 6.2.0
|
|
|
|
|
**Purpose:** Desktop application wrapper (Tauri 2)
|
2025-12-04 12:30:05 -03:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-21 23:40:38 -03:00
|
|
|
## ZERO TOLERANCE POLICY
|
|
|
|
|
|
|
|
|
|
**EVERY SINGLE WARNING MUST BE FIXED. NO EXCEPTIONS.**
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## ❌ ABSOLUTE PROHIBITIONS
|
2025-12-21 23:40:38 -03:00
|
|
|
|
|
|
|
|
```
|
2026-01-22 20:21:18 -03:00
|
|
|
❌ NEVER use #![allow()] or #[allow()] in source code
|
|
|
|
|
❌ NEVER use _ prefix for unused variables - DELETE or USE them
|
2025-12-21 23:40:38 -03:00
|
|
|
❌ NEVER use .unwrap() - use ? or proper error handling
|
|
|
|
|
❌ NEVER use .expect() - use ? or proper error handling
|
2026-01-22 20:21:18 -03:00
|
|
|
❌ NEVER use panic!() or unreachable!()
|
|
|
|
|
❌ NEVER use todo!() or unimplemented!()
|
|
|
|
|
❌ NEVER leave unused imports or dead code
|
|
|
|
|
❌ NEVER add comments - code must be self-documenting
|
2025-12-21 23:40:38 -03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 🔐 SECURITY - TAURI SPECIFIC
|
2026-01-08 13:16:02 -03:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
❌ NEVER trust user input from IPC commands
|
|
|
|
|
❌ NEVER expose filesystem paths to frontend without validation
|
|
|
|
|
❌ NEVER store secrets in plain text or localStorage
|
|
|
|
|
❌ NEVER disable CSP in tauri.conf.json for production
|
|
|
|
|
❌ NEVER use allowlist: all in Tauri configuration
|
|
|
|
|
```
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
### Path Validation
|
|
|
|
|
|
2026-01-08 13:16:02 -03:00
|
|
|
```rust
|
|
|
|
|
// ❌ WRONG - trusting user path
|
|
|
|
|
#[tauri::command]
|
|
|
|
|
async fn read_file(path: String) -> Result<String, String> {
|
|
|
|
|
std::fs::read_to_string(path).map_err(|e| e.to_string())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ CORRECT - validate and sandbox paths
|
|
|
|
|
#[tauri::command]
|
|
|
|
|
async fn read_file(app: tauri::AppHandle, filename: String) -> Result<String, String> {
|
|
|
|
|
let safe_name = filename
|
|
|
|
|
.chars()
|
|
|
|
|
.filter(|c| c.is_alphanumeric() || *c == '.' || *c == '-')
|
|
|
|
|
.collect::<String>();
|
|
|
|
|
if safe_name.contains("..") {
|
|
|
|
|
return Err("Invalid filename".into());
|
|
|
|
|
}
|
|
|
|
|
let base_dir = app.path().app_data_dir().map_err(|e| e.to_string())?;
|
|
|
|
|
let full_path = base_dir.join(&safe_name);
|
|
|
|
|
std::fs::read_to_string(full_path).map_err(|e| e.to_string())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 🏗️ ARCHITECTURE
|
2025-12-21 23:40:38 -03:00
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
### Structure
|
2025-12-04 12:30:05 -03:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
botapp/
|
|
|
|
|
├── src/
|
|
|
|
|
│ └── main.rs # Rust backend, Tauri commands
|
2026-01-22 20:21:18 -03:00
|
|
|
├── ui/
|
2025-12-04 12:30:05 -03:00
|
|
|
│ └── app-guides/ # App-specific HTML
|
|
|
|
|
├── js/
|
|
|
|
|
│ └── app-extensions.js # JavaScript extensions
|
|
|
|
|
├── icons/ # App icons (all sizes)
|
|
|
|
|
├── tauri.conf.json # Tauri configuration
|
2026-01-22 20:21:18 -03:00
|
|
|
└── Cargo.toml
|
2025-12-04 12:30:05 -03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Communication Flow
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Native UI (HTML/CSS/JS)
|
|
|
|
|
↓ Tauri IPC (invoke)
|
|
|
|
|
Rust #[tauri::command]
|
|
|
|
|
↓ HTTP (reqwest)
|
2025-12-12 23:20:08 -03:00
|
|
|
botserver API
|
2025-12-04 12:30:05 -03:00
|
|
|
↓
|
|
|
|
|
Business Logic + Database
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 🔧 TAURI COMMAND PATTERN
|
2025-12-04 12:30:05 -03:00
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
use tauri::command;
|
|
|
|
|
|
|
|
|
|
#[command]
|
|
|
|
|
pub async fn my_command(
|
|
|
|
|
window: tauri::Window,
|
|
|
|
|
param: String,
|
|
|
|
|
) -> Result<MyResponse, String> {
|
2026-01-08 13:16:02 -03:00
|
|
|
if param.is_empty() || param.len() > 1000 {
|
|
|
|
|
return Err("Invalid parameter".into());
|
|
|
|
|
}
|
2025-12-04 12:30:05 -03:00
|
|
|
Ok(MyResponse { /* ... */ })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
tauri::Builder::default()
|
|
|
|
|
.invoke_handler(tauri::generate_handler![
|
|
|
|
|
my_command,
|
|
|
|
|
])
|
|
|
|
|
.run(tauri::generate_context!())
|
2026-01-08 13:16:02 -03:00
|
|
|
.map_err(|e| format!("error running app: {e}"))?;
|
2025-12-04 12:30:05 -03:00
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JavaScript Invocation
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
const result = await window.__TAURI__.invoke('my_command', {
|
|
|
|
|
param: 'value'
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 🎨 ICONS - MANDATORY
|
2025-12-04 12:30:05 -03:00
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
**NEVER generate icons with LLM. Use official SVG icons from `botui/ui/suite/assets/icons/`**
|
2025-12-04 12:30:05 -03:00
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
Required icon sizes in `icons/`:
|
2025-12-04 12:30:05 -03:00
|
|
|
```
|
2026-01-22 20:21:18 -03:00
|
|
|
icon.ico # Windows (256x256)
|
|
|
|
|
icon.icns # macOS
|
|
|
|
|
icon.png # Linux (512x512)
|
|
|
|
|
32x32.png
|
|
|
|
|
128x128.png
|
|
|
|
|
128x128@2x.png
|
2025-12-04 12:30:05 -03:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## ⚙️ CONFIGURATION (tauri.conf.json)
|
2025-12-04 12:30:05 -03:00
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
2025-12-12 16:39:43 -03:00
|
|
|
"$schema": "https://schema.tauri.app/config/2",
|
|
|
|
|
"productName": "General Bots",
|
2026-01-22 20:21:18 -03:00
|
|
|
"version": "6.2.0",
|
2025-12-12 16:39:43 -03:00
|
|
|
"identifier": "br.com.pragmatismo.botapp",
|
2025-12-04 12:30:05 -03:00
|
|
|
"build": {
|
2025-12-12 16:39:43 -03:00
|
|
|
"devUrl": "http://localhost:3000",
|
|
|
|
|
"frontendDist": "../botui/ui/suite"
|
2025-12-04 12:30:05 -03:00
|
|
|
},
|
2025-12-12 16:39:43 -03:00
|
|
|
"app": {
|
|
|
|
|
"security": {
|
2026-01-08 13:16:02 -03:00
|
|
|
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
|
2026-01-22 20:21:18 -03:00
|
|
|
}
|
2025-12-04 12:30:05 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 📦 KEY DEPENDENCIES
|
2025-12-04 12:30:05 -03:00
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
| Library | Version | Purpose |
|
|
|
|
|
|---------|---------|---------|
|
|
|
|
|
| tauri | 2 | Desktop framework |
|
|
|
|
|
| tauri-plugin-dialog | 2 | File dialogs |
|
|
|
|
|
| tauri-plugin-opener | 2 | URL/file opener |
|
|
|
|
|
| botlib | path | Shared types |
|
|
|
|
|
| reqwest | 0.12 | HTTP client |
|
|
|
|
|
| tokio | 1.41 | Async runtime |
|
2025-12-04 12:30:05 -03:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-01-22 20:21:18 -03:00
|
|
|
## 🔑 REMEMBER
|
2025-12-21 23:40:38 -03:00
|
|
|
|
|
|
|
|
- **ZERO WARNINGS** - Every clippy warning must be fixed
|
|
|
|
|
- **NO ALLOW IN CODE** - Never use #[allow()] in source files
|
2026-01-22 20:21:18 -03:00
|
|
|
- **NO DEAD CODE** - Delete unused code
|
|
|
|
|
- **NO UNWRAP/EXPECT** - Use ? operator
|
|
|
|
|
- **Security** - Minimal allowlist, validate ALL inputs
|
2025-12-04 12:30:05 -03:00
|
|
|
- **Desktop-only features** - Shared logic in botserver
|
|
|
|
|
- **Tauri APIs** - No direct fs access from JS
|
2026-01-22 20:21:18 -03:00
|
|
|
- **Version 6.2.0** - do not change without approval
|