## 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