aeharding / aeharding/wingover
Settings: "Copy diagnostics" button — privacy-safe, no telemetry
- Ngôn ngữ chính
- TypeScript
- Star
- 0
- Fork
- 0
- Merge trung bình
- 4 giờ 2 phút
- Pull request đã merge (30 ngày)
- 6
Mô tả
## Why
The "Not subscribed" investigation (client fix #90; server side aeharding/wingover.app#4) took hours and ultimately required attaching Safari Web Inspector to a physical device and hand-dumping the Keychain. A one-tap **"Copy diagnostics"** in Settings would have made it a paste — and it fits our **no-telemetry** stance: the pilot copies a blob and chooses whether to share it; nothing phones home.
This is the privacy-scoped replacement for the postmortem's "client telemetry" item (telemetry is off the table).
## What it does
- A button in Settings (Support / About) → assembles a **redacted** diagnostics blob → copies to clipboard (and/or opens the share sheet).
- **No auto-send.** The pilot reviews and pastes it wherever they want.
- Pairs with the new `/v1/session` server logging (wingover.app#4): both sides key on `userId`, so a pasted client dump correlates directly with `docker logs deploy-api-1 | grep `.
## What to include
### Sync / subscription — the part that mattered most here
- Sync `state` (off / connecting / syncing / unsubscribed / error) and `readOnly`
- `held.entitled` (in-memory credential flag)
- The **stored (Keychain) credential's `entitled`** — a divergence between the live session response and the persisted copy is exactly what we were blind to
- `lastSyncedAt`, `SYNC_DISABLED`
- Credential: `environment` (Sandbox/Production), `dbName`, `userId`, `login` (apple/null) — **redact `password`**
- Last replication `error`, and the **last `denied` event (doc `_id` + reason)** — the invisible per-doc `forbidden` on `_design/auth` was the whole bug
### StoreKit — device-side subscription truth
- `appEnvironment()` — the build's StoreKit environment (Sandbox on TestFlight)
- `appleSubscriptionState()` — active / expired / null
- Whether a current entitlement exists; if so a **decoded summary only** (`expiresDate`, `environment`, `productId`) — **never the raw JWS**
### Identity / account
- `userId` (derived hash — safe, and the key to joining with server logs)
- account `environment`, `login`
- **Do NOT include** the SIWA `sub`, Apple ID, or email
### Build / platform
- App version (`__APP_VERSION__`) + build number / commit
- iOS version, native (Tauri) vs web, Tauri version
- Which credential store is live: **Keychain vs IndexedDB fallback**
### Local data
- Local flight/doc count + approx local DB size
- Whether a replication checkpoint / pending push exists
- **No flight content or GPS** — counts and sizes only
## Privacy / redaction rules
- **Never** include: CouchDB `password`, raw JWS / identity tokens, Apple ID / email / SIWA `sub`, flight GPS or content
- `userId` is a one-way hash of `appTransactionId + environment` → safe to include and the join key to server logs
- Clipboard/share only; the pilot decides what happens next
_Postmortem follow-up (A3). Related: #90, aeharding/wingover.app#4._
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Đánh giá
Issue này chưa được đánh giá.