# YMhut Box 反馈工单服务 这是 `server/feedback-mailer` 下的 Go + Gin + SQLite 反馈服务。旧 PHP 入口已移除,线上入口由 Go 服务接管;`config.txt`、`storage/`、`storage/feedback.sqlite` 和历史 `.ymfb` / `.zip` 文件继续保留并兼容读取。 ## 运行 在 `server/feedback-mailer` 目录直接运行: ```bash go run main.go ``` 监听地址以核心配置文件 `config.txt` 的 `listen` 为准: ```php 'listen' => ':8080', ``` 服务器部署时也可以显式设置服务根目录: ```bash export YMHUT_FEEDBACK_HOME=/opt/feedback-mailer ./feedback-mailer ``` 后台入口: ```text http://127.0.0.1:8080/admin/ ``` 生产构建与检查: ```bash npm --prefix admin-web install npm --prefix admin-web run build go test ./... go build . ``` ## 配置 优先读取当前目录的 `config.txt`,这是线上实际配置文件,部署时不要覆盖。没有 `config.txt` 时才回退读取 `config.json`。 关键字段: - `listen`:服务监听地址,例如 `:8080`、`:9090`、`127.0.0.1:8080`。 - `admin_password_hash` / `admin_password`:后台登录密码,推荐使用 bcrypt hash。 - `client_signature_key`:旧 WinUI 客户端 HMAC 签名密钥,必须保持一致。 - `package_encryption_key`:`.ymfb` 反馈包解密密钥,必须保持一致。 - `storage_dir`:默认 `storage`,保留历史反馈包。 - `database_path`:默认 `storage/feedback.sqlite`,保留旧 SQLite 数据。 - `rate_limit`:提交、状态查询、验证码、登录和后台 API 的令牌桶限流。 - `upload_guard`:zip 文件数量、解压后大小、单文件大小、压缩比、路径穿越校验。 - `backup.dir` / `backup_dir`:数据库只读备份输出目录,默认 `storage/backups`。 - `webhooks`:通用 Webhook 通知配置,secret 只用于签名,不进入 URL 或配置健康 API。 ## 兼容接口 旧客户端提交接口保持不变: ```text POST / ``` 继续接收 `payload`、`timestamp`、`nonce`、`packageSha256`、`signature`、`package`,并保留旧错误码。 旧状态查询保持不变: ```text GET /?api=status&code=FB-YYYYMMDD-XXXXXX ``` 响应保留旧字段,并兼容增加 `statusDetail`、`category`、`priority`。 ## 后台能力 - 公共首页 `/`:反馈中心正式页和无需登录的状态查询。 - 后台 `/admin/`:工作台、工单流、状态看板、通知记录、Webhook 集成、运维、配置健康。 - 10 秒轮询刷新:统计卡片、SVG 图表、工单列表、详情、通知和配置摘要都会重绘。 - 工单增强:状态、分类、优先级、SLA、指派人、截止时间、标签、评论、解决说明、内部备注、公开回复。 - 看板操作:按 `new / triaged / investigating / resolved / archived` 分栏,拖动工单即可改状态。 - 批量处理:多选后批量归类、处理中、解决、归档。 - 导出:`GET /api/admin/feedbacks/export?format=csv` 导出当前筛选结果,不包含包文件和密钥。 - 审计日志:登录、工单修改、批量操作、导出、备份、Webhook 测试等都会记录。 - 数据库备份:后台创建和下载 SQLite 备份,不提供在线删除、VACUUM 或破坏性维护。 - Webhook:支持 `feedback.created`、`feedback.updated`、`feedback.status_changed`、`feedback.comment_created`、`mail.failed`。 Webhook 请求头: ```text X-YMhut-Event X-YMhut-Delivery X-YMhut-Signature ``` 签名格式为 `sha256=`。 ## 数据升级 服务启动时会对旧 `feedbacks` 表做非破坏性补列,并创建新表: - `feedback_comments` - `feedback_tags` - `audit_logs` - `webhook_deliveries` - `feedback_events` SQLite 默认启用 WAL,并设置 `busy_timeout`。不会删除 `storage/feedback.sqlite`,不会修改历史 `.ymfb`、`.zip` 文件。 ## 后台 API 需要登录 session,写接口需要 CSRF: - `GET /api/admin/overview` - `GET /api/admin/config` - `GET /api/admin/feedbacks?page=&perPage=&status=&category=&priority=&mail=&q=&assignee=&tag=&sla=&overdue=&sort=` - `GET /api/admin/feedbacks/export?format=csv` - `GET /api/admin/feedbacks/summary` - `GET /api/admin/feedbacks/:code` - `PATCH /api/admin/feedbacks/:code` - `PATCH /api/admin/feedbacks/bulk` - `POST /api/admin/feedbacks/:code/comments` - `GET /api/admin/mails?page=&perPage=&status=` - `POST /api/admin/mails/test` - `GET /api/admin/audit-logs?page=&perPage=&actor=&type=` - `GET /api/admin/webhooks/deliveries?page=&perPage=&status=` - `POST /api/admin/webhooks/test` - `POST /api/admin/backups/database` - `GET /api/admin/backups` - `GET /api/admin/backups/:name` ## 增强依据 - OWASP File Upload Cheat Sheet:上传限额、存储隔离、路径和内容校验、防 zip bomb。 - OWASP REST Security Cheat Sheet:限流、审计、避免敏感信息出现在 URL、统一错误语义。 - SQLite WAL 与备份文档:读写并发和在线备份思路。 - Go `golang.org/x/time/rate`:内存令牌桶限流。 - Gin graceful shutdown 示例:使用 `http.Server.Shutdown()` 优雅停机。 ## 验证 ```bash go test ./... go build . npm --prefix admin-web run build go run main.go ``` 启动后建议检查: ```text http://127.0.0.1:8080/ http://127.0.0.1:8080/admin/ http://127.0.0.1:8080/?api=status&code=BAD http://127.0.0.1:8080/api/auth/captcha ```