## Why 当前 `SmsReceive` 已经具备短信原文接收、存储和本地诊断能力。新需求是在收到字符串内容后,把它发送到服务器。用户已经给出 Python 参考实现,目标服务器实际是飞书机器人 webhook:构造 interactive markdown 卡片,使用 `timestamp + "\n" + secret` 生成 HmacSHA256 + Base64 签名,然后 POST 到 `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。 这次变更的重点不是重新设计服务端协议,而是把 Python 中已经验证过的请求协议等价迁移到 Android,并与当前短信接收链路解耦。Android 侧应提供一个可测试、可诊断、可复用的发送模块,后续可以由 `SmsReceiver`、手动测试按钮或其它业务入口调用。 ## What Changes - 新增飞书 webhook 推送规格,覆盖: - 签名算法:保持与 Python `generate_sign(secret, timestamp)` 完全一致。 - 请求体:保持 `msg_type=interactive`,卡片元素为 markdown content。 - URL:`https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。 - 网络请求:Android 侧使用 OkHttp 作为首选实现,避免为了一个简单 POST 引入 Retrofit 接口层。 - 线程模型:所有网络请求必须在后台线程执行,不能阻塞 `BroadcastReceiver.onReceive` 或主线程。 - 结果判断:HTTP 200 且响应 JSON `code == 0` 才视为成功。 - 失败诊断:区分签名失败、参数缺失、HTTP 非 200、响应 JSON 异常、飞书业务错误码、网络异常和超时。 - 新增轻量配置入口: - `webhook_id`、`secret` 不写死在代码中。 - 实际配置从 `/sdcard/Android/data/{applicationId}/config/feishu.json` 读取,便于动态调试。 - 如果 `feishu.json` 不存在,则生成默认模板 `/sdcard/Android/data/{applicationId}/config/def_config_feishu.json`。 - 后续实现可接入当前短信结果: - 成功读取短信原文后,可以把短信内容、来源、时间和发送方掩码作为 markdown 内容推送。 - 默认推送完整短信原文,便于确认服务端收到的内容与本机短信一致。 ## Capabilities ### New Capabilities - `feishu-webhook-push`: 定义 Android 侧飞书机器人 webhook 推送能力,包括签名、请求体、网络执行、响应解析、错误诊断和隐私边界。 ### Modified Capabilities - `sms-code-capture`: 后续实现可以在短信原文读取成功后触发推送,但短信捕获本身不依赖网络成功。 - `sms-receiver-delivery-diagnostics`: 后续诊断应区分“短信接收/解析成功”和“远端推送成功/失败”,避免把网络失败误判为短信接收失败。 ## Impact - 预期后续会修改: - `app/build.gradle`:新增 OkHttp 依赖,必要时新增 JSON 解析依赖或使用 `org.json`。 - `app/src/main/AndroidManifest.xml`:新增 `android.permission.INTERNET`。 - `app/src/main/java/com/smsreceive/app/`:新增飞书推送相关 Java 类,例如 `FeishuWebhookClient`、`FeishuWebhookConfigStore`、`FeishuWebhookPushResult`。 - `MainActivity`:新增 JSON 配置路径展示、配置输入、测试发送和最近推送结果展示。 - `SmsReceiver` 或统一结果处理层:在短信原文读取成功后触发异步推送。 - 推荐技术选择: - 网络库:OkHttp。 - JSON 构造/解析:优先使用 Android 自带 `org.json`,降低依赖数量。 - 签名:`javax.crypto.Mac` + `SecretKeySpec` + `android.util.Base64.NO_WRAP`。 - 异步执行:小型 `ExecutorService` 或现有轻量后台执行器,不引入协程/RxJava。 - 隐私影响: - 默认推送短信原文、来源、发送方掩码和时间。 - 不在 logcat 打印 secret、sign、完整 webhook URL 或完整短信正文。 ## Validation - OpenSpec 文档结构完整,包含 `proposal.md`、`design.md`、`tasks.md` 和 capability spec。 - 方案必须能解释以下问题: - Python 签名算法如何在 Android 中等价实现。 - 为什么首选 OkHttp 而不是 Retrofit。 - 为什么网络请求不能直接在 `BroadcastReceiver.onReceive` 内同步执行。 - 如何判断推送成功,以及失败时如何诊断。 - 哪些短信内容可以上传,哪些默认不上传。 - 后续代码完成后: - 签名单元测试使用固定 `secret` 和 `timestamp` 对比 Python 算法输出。 - 请求体构造测试验证 JSON 字段与 Python 参考实现一致。 - 响应解析测试覆盖 `code == 0`、业务错误码、非 JSON 响应。 - 不要求本轮编译;代码完成后通知用户即可。 - 每次 commit 或 push 前必须检查 diff,避免引入非预期 EOF newline 变化。