271 lines
No EOL
11 KiB
Markdown
271 lines
No EOL
11 KiB
Markdown
---
|
||
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_LINE–END_LINE covering DD.MM–DD.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. |