tangem-app-android-audited/.claude/skills/analyze-logs/SKILL.md
2026-06-01 14:56:59 +03:00

271 lines
No EOL
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: analyze-logs
description: Analyze Tangem app user logs — extract device info, navigation path, errors, and key events timeline. Use when user provides a log file for bug investigation.
allowed-tools: Read, Grep
argument-hint: /path/to/logfile.txt [/path/to/logs.rtf] [--no-secrets-audit]
---
Analyze the Tangem app user log file at path: `$ARGUMENTS`
## File Input
The user provides one or two file paths:
- **Log file** (`.txt`) — main application log, always required
- **User info file** (`.rtf` or `.txt`) — optional, contains card/device/error info from the user's feedback email
If two paths are provided, the first is the log file and the second is the user info file.
**If only the log file is provided**, ask the user if they have a user info file (`logs.rtf` or `logs.txt`). If they don't have it or don't respond, fill Device Context, Card Info, and Transaction Context sections from the log file data (Steps 2+3). Mark fields that could not be determined as "N/A".
## User Info File (logs.rtf / logs.txt)
If a user info file is provided, Read it and extract the plain text fields. The file contains structured key-value pairs like:
```
Card ID: AF36000002151580
Firmware version: 6.33r
Linked cards count: 2
Has seed phrase: true
Signed hashes [secp256k1]: 0
----------
Blockchain: Polygon
Explorer link: https://polygonscan.com/address/0x...
Derivation path: m/44'/60'/0'/0/0
Host: https://rpc-mainnet.matic.quiknode.pro/
Token: USDC
Error: Could not construct a recoverable key.
----------
Source address: 0x...
Destination address: 0x...
Amount: 11.319684
Fee: 0.004973
----------
Phone model: SM-S921B
OS version: 36
App version: 5.34.1
```
Extract all fields and include them in the **Device Context**, **Card Info**, and **Analysis Summary** sections of the report. If the RTF contains an `Error:` field, treat it as a key clue for the investigation.
Note: RTF files contain formatting markup (`\cb3`, `\cf4`, `{\field{...}}`). Ignore all RTF tags — only extract the plain text values after each colon.
## Log Format
Each line follows the pattern:
```
DD.MM HH:MM:SS.mmm: TAG Message
```
- Date format: `DD.MM` (day.month), no year — infer from context
- Multi-line entries (JSON bodies, stack traces) continue without the timestamp prefix
- Sensitive data is masked with `******`
- Continuation lines may start with `|` for structured data: `|- Duration millis: 300000`
## Analysis Steps
Use `head_limit` on every Grep call to protect context from overload.
### Step 1: Setup
1. **Log time range:** Read the first and last lines with dates (format `DD.MM`)
2. **Ask the user** (report time range, then ask):
- Date range to focus on (or "all" for the full file)
- Focus area: `Wallet`, `WalletConnect`, `Express (Onramp/Buy, Offramp/Sell, Swap/Exchange)`, `TangemPay`, `Feed`, `Markets`, `Settings`, `Referral`, `Staking`, `Onboarding`, `Send/Transactions`, `NFT`, or `all`
- Remember the chosen area as **FOCUS_AREA**
3. **Determine line range** (skip if "all"):
- Parse input into `DD.MM` patterns (`10-13.03` → start `10.03`, end `13.03`; `last day` → last date; `last 3 days` → 3 days before last)
- Find **START_LINE**: Grep `^START_DATE` (head_limit: 1, -n: true)
- Find **END_LINE**: Grep `^NEXT_DATE` (head_limit: 1, -n: true). If not found, END_LINE = end of file
- Report: "Focusing on lines START_LINEEND_LINE covering DD.MMDD.MM"
### Steps 2+3+4+5+6: Main Analysis (all in parallel)
Launch ALL Grep calls below in parallel. Steps 2+3 search the **full file** (device info may be before the date range). Steps 4+5+6 use `offset: START_LINE` to stay within the date range.
**Device Context (full file):**
- `PATCH.*user-wallets/applications` (head_limit: 5, -A 10) — Read JSON body to extract `systemVersion`, `version`, `language`, `timezone`
- `ip_address` (head_limit: 5, -A 20) — extract `alpha2`, `country`, `isBuyAllowed`, `isSellAllowed`
**Card Info (full file):**
- `CardSDK_Tlv.*TAG_Firmware` (head_limit: 20)
- `CardSDK_Tlv.*TAG_SettingsMask` (head_limit: 20)
- `CardSDK_Tlv.*TAG_IsActivated` (head_limit: 20)
- `CardSDK_Tlv.*TAG_ManufacturerName` (head_limit: 20)
**Navigation (offset: START_LINE):**
- `AppRouter` (head_limit: 200) — if FOCUS_AREA is `all` or navigation-heavy (Wallet, Onboarding, Send/Transactions), also Read `.claude/docs/navigation-graph.md` to cross-reference routes
**Errors (offset: START_LINE, head_limit: 50 each, -n: true):**
- HTTP errors: `<-- [45]\d{2}`
- Domain errors: `DomainError`
- App exceptions: `\bException\b`
- Biometric errors: `onAuthenticationError`
- Tangem Pay errors: `Failed checkCustomerWallet`
**Session timeline (offset: START_LINE, head_limit: 50 each):**
- `MainActivity.*onCreate` — app session start
- `MainActivity.*Splash screen` — splash screen installed/dismissed
- `MainActivity.*onNewIntent` — deep link or push notification
- `CardSDK_Session.*start card session` — NFC session starts
**Secrets & PII Audit (full file, head_limit: 20 each, -n: true):**
Skip this entire group if `--no-secrets-audit` is in arguments.
- API key leak in URL: `[?&](api[_-]?key|apiKey|access_token|token|secret)=(?!\*+)[^&\s]{8,}`
- Bearer token: `Bearer\s+[A-Za-z0-9._\-]{20,}`
- JWT: `eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+`
- Authorization header: `(?i)authorization:\s*\S+`
- Critical PII in JSON: `"(privateKey|mnemonic|seedPhrase|private_key|seed_phrase)"\s*:\s*"[^"]+"`
- card_public_key in JSON: `"card_public_key"\s*:\s*"[^"]{40,}"`
- FCM push token: `:APA91[A-Za-z0-9_\-]{100,}`
- xprv/tprv extended private key: `\b[xytzuv]prv[A-Za-z0-9]{100,}`
- Suspicious long hex in URL path: `https?://[^?\s]+/[A-Fa-f0-9]{32,}\b`
- Masking health check: count of `\*{6,}` — if 0 in a build that should mask, flag pipeline broken
**Error filtering:** When processing error results, skip these noisy matches:
- `java.io.IOException: Canceled` — normal request cancellation
- `HttpException(code=304` — HTTP "Not Modified"
- Bare stacktrace lines starting with `\tat`
- `<-- HTTP FAILED: java.io.IOException: Canceled`
### Step 6.5: Masking Consistency Check
Skip if `--no-secrets-audit` in arguments. Run sequentially after the parallel batch (needs results from the masked-endpoint grep).
1. Grep `https?://[^/\s]+/[^\s*]*\*{6,}` (full file, head_limit: 50) — collect all URLs where a path segment is masked
2. For each unique `host + path-prefix-before-mask`, derive the prefix string
3. For each prefix, Grep the prefix followed by a non-`*` character (`<prefix>[^*\s]`, head_limit: 20)
- If hits found → masking inconsistency: same endpoint has both masked and unmasked variants
- Record the prefix, count of masked hits, count of unmasked hits, first unmasked line number
### Step 7: Deep Dive
For each significant error found above:
1. Note the error's line number from Grep output (`-n: true`)
2. Use Read with `offset: ERROR_LINE - 100, limit: 200` to get ~200 lines of context
3. In that context, look for navigation events, API calls, and redux actions
## Key Tags Reference
| Tag | Purpose |
|-----|---------|
| `MainActivity` | Activity lifecycle, splash screen, onNewIntent |
| `AppRouter` | Navigation: Push, Pop, Replace |
| `NetworkLogs` | HTTP requests/responses (OkHttp) |
| `BlockchainSDK_NETWORK` | Blockchain RPC calls |
| `CardSDK_Tlv` | NFC card data (firmware, settings) |
| `CardSDK_Session` | NFC session lifecycle |
| `CardSDK_Biometric` | Biometric authentication |
## Common Error Patterns
| Pattern | Meaning |
|---------|---------|
| `HttpException(code=4xx/5xx, errorBody={...})` | API error with structured body |
| `DomainError(description=...)` | App-level domain error |
| `<-- HTTP FAILED: java.io.IOException: Canceled` | Cancelled network request (noise) |
| `<-- 429` | Rate limiting |
| `onAuthenticationError` | Biometric auth failure |
## Output Template
Structure your report EXACTLY as follows:
```
# Log Analysis Report
## Device Context
| Parameter | Value |
|-----------|-------|
| App version | ... |
| Android version | ... |
| Phone model | ... (from logs.rtf if available) |
| Language | ... |
| Timezone | ... |
| Country | ... |
| Log time range | DD.MM HH:MM — DD.MM HH:MM |
## Card Info
| Parameter | Value |
|-----------|-------|
| Card ID | ... (from logs.rtf if available) |
| Firmware | ... |
| Manufacturer | ... |
| Is activated | ... |
| Linked cards | ... (from logs.rtf if available) |
| Has seed phrase | ... (from logs.rtf if available) |
## Transaction Context (from logs.rtf, if available)
| Parameter | Value |
|-----------|-------|
| Blockchain | ... |
| Token | ... |
| Source address | ... |
| Destination address | ... |
| Amount | ... |
| Fee | ... |
| Error | ... |
## Navigation Path
1. [HH:MM:SS] Screen (Push/Pop/Replace)
2. ...
**Summary:** Brief description of the user's journey.
## Errors Found
### HTTP Errors
| Time | URL | Status | Details |
|------|-----|--------|---------|
### Domain Errors
| Time | Component | Error |
|------|-----------|-------|
### Other Errors
| Time | Type | Details |
|------|------|---------|
## Key Events Timeline
| Time | Event | Details |
|------|-------|---------|
(chronological: app starts, card sessions, navigation, errors, notable API calls)
## Secrets & PII Audit
Omit this section entirely if `--no-secrets-audit` was passed.
### Health Check
- Total masked tokens (`******`) in log: **N**
- If N = 0 in a build expected to mask, flag: "masking pipeline may be broken"
### Confirmed Leaks (CRITICAL / HIGH)
| Line | Severity | Type | Matched (first 16 chars + `…`) | Context |
|------|----------|------|--------------------------------|---------|
### Masking Inconsistencies
| Endpoint Prefix | Masked Hits | Unmasked Hits | First Unmasked Line |
|-----------------|-------------|---------------|---------------------|
### Suspected Leaks (MEDIUM / LOW)
| Line | Severity | Type | Pattern Matched | Why Suspect |
|------|----------|------|-----------------|-------------|
**Severity legend:**
- **CRITICAL** — private key / mnemonic / xprv in clear text
- **HIGH** — API key / bearer / JWT / card_public_key visible
- **MEDIUM** — push token, card_id, persistent identifiers
- **LOW** — heuristic patterns that may be false positives (tx hash, content hash)
**Output rules:**
- Never include the full matched value — always truncate to 16 chars + `…`
- For LOW severity, add a "Why Suspect" column explaining typical false positives
- Skip matches from these known-public Tangem endpoints: `/v1/coins/settings`, `/v1/geo`, `/v1/currencies`, `/v1/hot_crypto`
## Analysis Summary
(2-3 paragraphs: what the user was doing, what broke, probable cause, recommendations.
If FOCUS_AREA was specified, emphasize errors, navigation, and API calls related to that area.)
```
If a section has no data, write "None found" instead of omitting it.