- 删除 VerificationCodeParser 及相关测试,短信捕获和推送不再解析验证码 - 飞书推送改为只发送短信原文,时间戳格式化为可读日期 - 移除主界面"只推送验证码"开关和"调试时上传完整短信正文"选项 - 移除"保存轮询间隔"按钮,开启轮询时自动保存间隔(未输入默认1秒) - 按钮文字从"开始1秒轮询验证码"改为"开始短信轮询" - 删除"打印最近30条短信"功能及相关 SmsInboxReader.logRecentMessages - SmsInboxReader 用 RecentSmsResult 替换 RecentCodeResult - FeishuWebhookConfigStore.Config 移除 filterVerificationCode/sendFullBodyDebug - 修复代码缩进不一致问题
96 lines
4.9 KiB
Markdown
96 lines
4.9 KiB
Markdown
## ADDED Requirements
|
|
|
|
### Requirement: Generate Feishu webhook signatures equivalent to the Python reference
|
|
The app SHALL generate Feishu webhook signatures with the same algorithm and input layout as the provided Python implementation.
|
|
|
|
#### Scenario: Signature is generated for a timestamp and secret
|
|
- **WHEN** the app signs a request with a second-level timestamp and secret
|
|
- **THEN** it MUST build the signing key as `timestamp + "\n" + secret`
|
|
- **AND** it MUST use HmacSHA256 with an empty message body
|
|
- **AND** it MUST return a Base64 encoded signature without inserted line breaks
|
|
|
|
#### Scenario: Signing fails
|
|
- **WHEN** the HMAC algorithm or key initialization fails
|
|
- **THEN** the app MUST return a structured `sign_error`
|
|
- **AND** it MUST NOT attempt to send the webhook request
|
|
|
|
### Requirement: Send interactive markdown cards to Feishu webhook
|
|
The app SHALL send markdown content to the Feishu bot webhook using the same request structure as the Python reference.
|
|
|
|
#### Scenario: Markdown content is sent
|
|
- **WHEN** push is enabled and webhook configuration is valid
|
|
- **THEN** the app MUST POST JSON to `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`
|
|
- **AND** the JSON body MUST contain `msg_type` as `interactive`
|
|
- **AND** the JSON body MUST contain a card element with `tag` as `markdown` and `content` as the markdown string
|
|
- **AND** the JSON body MUST contain `timestamp` as a string and `sign` as the generated signature
|
|
|
|
#### Scenario: Webhook configuration is missing
|
|
- **WHEN** push is requested without a webhook id or secret
|
|
- **THEN** the app MUST return a structured `missing_config` result
|
|
- **AND** it MUST NOT perform a network request
|
|
|
|
### Requirement: Execute webhook network requests off the main and broadcast threads
|
|
The app SHALL avoid blocking UI and SMS broadcast handling while sending webhook requests.
|
|
|
|
#### Scenario: SMS receiver triggers a push
|
|
- **WHEN** a new SMS capture result is stored successfully in `SmsReceiver`
|
|
- **THEN** the app MUST save the local capture result first
|
|
- **AND** it MUST dispatch the webhook push asynchronously
|
|
- **AND** it MUST NOT wait for the network request before returning from broadcast handling
|
|
|
|
#### Scenario: User sends a test push
|
|
- **WHEN** the user taps a test push action in the UI
|
|
- **THEN** the app MUST run the network request on a background executor
|
|
- **AND** it MUST update the latest push status when the request completes
|
|
|
|
### Requirement: Classify webhook push results
|
|
The app SHALL classify success and failure states so SMS receiving diagnostics remain separate from network diagnostics.
|
|
|
|
#### Scenario: Feishu returns success
|
|
- **WHEN** the HTTP status is 200 and the response JSON contains `code` equal to 0
|
|
- **THEN** the app MUST record the push as successful
|
|
|
|
#### Scenario: HTTP status is not successful
|
|
- **WHEN** the webhook response HTTP status is not 200
|
|
- **THEN** the app MUST record an `http_error` with the HTTP status code
|
|
|
|
#### Scenario: Response is not valid JSON
|
|
- **WHEN** the webhook response body cannot be parsed as JSON
|
|
- **THEN** the app MUST record an `invalid_json` result
|
|
|
|
#### Scenario: Feishu returns a business error
|
|
- **WHEN** the webhook response JSON contains `code` not equal to 0
|
|
- **THEN** the app MUST record an `api_error`
|
|
- **AND** it MUST include the Feishu `code` and `msg` when available
|
|
|
|
#### Scenario: Network request fails or times out
|
|
- **WHEN** OkHttp reports an I/O failure
|
|
- **THEN** the app MUST record `network_error` or `timeout` according to the failure type
|
|
|
|
### Requirement: Keep webhook configuration private while pushing complete SMS content
|
|
The app SHALL avoid exposing webhook secrets while sending complete SMS content for debugging.
|
|
|
|
#### Scenario: Runtime config is loaded
|
|
- **WHEN** the app needs Feishu webhook settings
|
|
- **THEN** it MUST read them from `/sdcard/Android/data/{applicationId}/config/feishu.json`
|
|
- **AND** changing that JSON file MUST NOT require recompiling Android code
|
|
|
|
#### Scenario: Runtime config file is missing
|
|
- **WHEN** `/sdcard/Android/data/{applicationId}/config/feishu.json` does not exist
|
|
- **THEN** the app MUST create `/sdcard/Android/data/{applicationId}/config/def_config_feishu.json`
|
|
- **AND** it MUST keep remote push disabled until a valid `feishu.json` is provided or saved
|
|
|
|
#### Scenario: Configuration is displayed or logged
|
|
- **WHEN** the app displays or logs webhook configuration
|
|
- **THEN** it MUST mask the secret
|
|
- **AND** it MUST NOT log the generated signature or full webhook URL
|
|
|
|
#### Scenario: SMS push content is built
|
|
- **WHEN** the app builds markdown content from an SMS capture result
|
|
- **THEN** it MUST include the full original SMS body and minimal diagnostics such as source, masked sender, time, and any structured failure reason when present
|
|
|
|
#### Scenario: Webhook push is disabled
|
|
- **WHEN** an SMS is captured while push is disabled
|
|
- **THEN** the app MUST keep local SMS capture behavior unchanged
|
|
- **AND** it MUST record or report that remote push was skipped because it is disabled
|