Initial commit: email-openclaw bridge v1
Full pipeline: IMAP ingress -> OpenClaw dispatch -> callback -> SMTP reply. SQLite stateful storage with idempotency, threading, and retry logic. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# Checkpoint 001 — Project Scaffold
|
||||
|
||||
**Ngày:** 2026-04-24
|
||||
**Trạng thái:** ✅ Hoàn thành
|
||||
**Verify:** `go build ./...` thành công, không lỗi
|
||||
|
||||
---
|
||||
|
||||
## Việc đã làm
|
||||
|
||||
### 1. Khởi tạo Go module
|
||||
```
|
||||
go mod init github.com/thuanle/claw-email
|
||||
```
|
||||
|
||||
### 2. Tạo cấu trúc thư mục
|
||||
|
||||
```
|
||||
claw-email/
|
||||
├── cmd/bridge/main.go # Entrypoint
|
||||
├── internal/
|
||||
│ ├── config/config.go # Đọc .env, validate required vars
|
||||
│ ├── database/
|
||||
│ │ ├── database.go # Open SQLite + auto-migrate + health check
|
||||
│ │ └── models.go # Task model (đầy đủ schema từ requirements)
|
||||
│ ├── logging/logger.go # Structured JSON logging (slog)
|
||||
│ ├── api/router.go # Gin router: /healthz, /readyz
|
||||
│ ├── mail/mail.go # [stub] IMAP ingress + SMTP egress
|
||||
│ └── ai_client/client.go # [stub] OpenClaw HTTP dispatch
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
├── Dockerfile # Multi-stage, CGO_ENABLED=0
|
||||
├── docker-compose.yml # Named volume cho SQLite
|
||||
├── go.mod / go.sum
|
||||
└── requirements.md
|
||||
```
|
||||
|
||||
### 3. Kết nối SQLite + auto-migrate bảng `tasks`
|
||||
- Driver: `github.com/glebarez/sqlite` (pure Go, wraps `modernc.org/sqlite`)
|
||||
- WAL mode enabled
|
||||
- Auto-migrate bảng `tasks` khi khởi động
|
||||
- Health check: `SELECT 1`
|
||||
|
||||
### 4. Module config (.env)
|
||||
- Dùng `github.com/joho/godotenv` load `.env`
|
||||
- Validate tất cả biến bắt buộc, trả lỗi rõ ràng nếu thiếu
|
||||
- Parse `WHITELIST_EMAILS` (comma-separated)
|
||||
- Default `LISTEN_ADDR=:8080`
|
||||
|
||||
### 5. Structured Logging
|
||||
- Dùng `log/slog` (Go stdlib 1.21+), JSON handler ra stdout
|
||||
- Helper `TaskLogger(taskUUID, threadID, messageID)` — mọi log liên quan task đều có context
|
||||
|
||||
### 6. API endpoints (Gin)
|
||||
- `GET /healthz` → `200 {"status":"ok"}` (liveness)
|
||||
- `GET /readyz` → kiểm tra DB writable + config token (readiness)
|
||||
|
||||
### 7. Docker
|
||||
- **Dockerfile**: Multi-stage, `golang:1.23-alpine` → `alpine:3.20`, `CGO_ENABLED=0`
|
||||
- **docker-compose.yml**: Named volume `bridge-data:/app/data`, `env_file: .env`
|
||||
|
||||
---
|
||||
|
||||
## Quyết định thiết kế
|
||||
|
||||
| Quyết định | Lý do |
|
||||
|---|---|
|
||||
| `glebarez/sqlite` thay vì `gorm.io/driver/sqlite` | Pure Go, không cần CGO → Docker build đơn giản |
|
||||
| `log/slog` thay vì zap/logrus | Stdlib, zero dependency, đủ dùng |
|
||||
| `gin-gonic/gin` | Đúng requirements, nhẹ, phổ biến |
|
||||
| WAL mode SQLite | Tăng throughput đọc concurrent |
|
||||
| `internal/` layout | Chuẩn Go, ngăn import từ bên ngoài |
|
||||
|
||||
## Dependencies (go.mod)
|
||||
|
||||
```
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/glebarez/sqlite v1.11.0 (→ modernc.org/sqlite)
|
||||
github.com/joho/godotenv v1.5.1
|
||||
gorm.io/gorm v1.31.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tiếp theo (chưa implement)
|
||||
|
||||
1. IMAP Ingress — IDLE, anti-loop, whitelist, idempotency, threading
|
||||
2. OpenClaw Dispatch — HTTP POST, retry 3 lần (1s/5s/15s)
|
||||
3. Callback handler — webhook xác thực token, cập nhật task
|
||||
4. SMTP Egress — gửi reply, In-Reply-To/References, retry
|
||||
5. Integration tests — 6 scenarios từ requirements
|
||||
Reference in New Issue
Block a user