2026-05-18 11:10:52 +08:00

97 lines
5.0 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 verification code is parsed 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: Verification code push content is built
- **WHEN** the app builds markdown content from a parsed SMS result
- **THEN** it MUST include the verification code and minimal diagnostics such as source, masked sender, time, strategy, and confidence
- **AND** it MUST include the full original SMS body
#### Scenario: Webhook push is disabled
- **WHEN** a verification code is parsed 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