|
| 1 | +# Smart Key Extraction Confirmation Dialog Spec |
| 2 | + |
| 3 | +> Last updated: 2026-03-18 |
| 4 | +
|
| 5 | +## Overview |
| 6 | + |
| 7 | +The Smart Key Extraction confirmation dialog is an inline content script UI in the Chrome Extension. When a detected key's confidence falls between 0.35 and 0.7 (medium tier), the system masks the key first, then displays a confirmation dialog for the user to decide whether to store it. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Three-Tier Confidence Strategy |
| 12 | + |
| 13 | +| Confidence Range | Action | Description | |
| 14 | +|-----------------|--------|-------------| |
| 15 | +| >= 0.7 (high) | Auto-store | Send `submit_captured_key` to Core directly, show toast | |
| 16 | +| 0.35 ~ 0.7 (medium) | Mask + confirmation dialog | Mask plaintext first, show inline dialog for user confirmation | |
| 17 | +| < 0.35 (low) | Ignore | No processing, no masking | |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Confirmation Dialog UI Design |
| 22 | + |
| 23 | +``` |
| 24 | ++--------------------------------------------------+ |
| 25 | +| DemoSafe: Detected possible API key | |
| 26 | +| | |
| 27 | +| Service name: [__openai______________] (editable)| |
| 28 | +| Key preview: sk-proj-...xxxx | |
| 29 | +| | |
| 30 | +| [ Confirm & Store ] [ Reject ] (27s) | |
| 31 | ++--------------------------------------------------+ |
| 32 | +``` |
| 33 | + |
| 34 | +### UI Elements |
| 35 | + |
| 36 | +| Element | Description | |
| 37 | +|---------|-------------| |
| 38 | +| Title | "DemoSafe: Detected possible API key" | |
| 39 | +| Service name | Editable text input, defaults to detected platform name | |
| 40 | +| Key preview | Masked key preview (prefix + ...last 4 chars) | |
| 41 | +| Confirm & Store | Confirm button, submits to Core for storage | |
| 42 | +| Reject | Reject button, restores original text and adds to rejectedKeys | |
| 43 | +| Countdown | Bottom-right displays remaining seconds, 30s auto-dismiss | |
| 44 | + |
| 45 | +### Behavior Table |
| 46 | + |
| 47 | +| Action | Behavior | |
| 48 | +|--------|----------| |
| 49 | +| Confirm | Send `submit_captured_key` to background -> Core, close dialog, key stays masked | |
| 50 | +| Reject | Restore key's original text, add to `rejectedKeys` Set, close dialog | |
| 51 | +| Escape | Same as Reject | |
| 52 | +| 30s timeout | Auto-dismiss, key stays masked (neither submitted nor restored) | |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## Queue Mechanism |
| 57 | + |
| 58 | +When multiple medium-confidence keys are detected simultaneously on a page, dialogs are shown sequentially via a queue: |
| 59 | + |
| 60 | +1. First key's dialog appears immediately |
| 61 | +2. Subsequent keys are added to the `pendingConfirmations` queue |
| 62 | +3. After previous dialog closes, the next one automatically appears |
| 63 | +4. Each dialog has its own independent 30s countdown |
| 64 | + |
| 65 | +--- |
| 66 | + |
| 67 | +## Deduplication Mechanism |
| 68 | + |
| 69 | +Three Sets prevent duplicate processing: |
| 70 | + |
| 71 | +| Set | Purpose | Lifetime | |
| 72 | +|-----|---------|----------| |
| 73 | +| `submittedKeys` | Keys already submitted to Core (high-confidence auto + confirmed) | Page lifetime | |
| 74 | +| `rejectedKeys` | Keys rejected by the user | Page lifetime | |
| 75 | +| `isAlreadyStoredKey()` | Query Core for known keys (via pattern matching) | Real-time query | |
| 76 | + |
| 77 | +Flow: key detected -> check submittedKeys / rejectedKeys / isAlreadyStoredKey -> skip if exists -> otherwise route by confidence tier. |
| 78 | + |
| 79 | +--- |
| 80 | + |
| 81 | +## Universal Masking / Detection Toggles |
| 82 | + |
| 83 | +### Popup UI |
| 84 | + |
| 85 | +Two independent toggle switches in the popup panel: |
| 86 | + |
| 87 | +- **Universal Masking**: Enable DOM masking on non-supported platform pages (default OFF) |
| 88 | +- **Universal Detection**: Enable key detection on non-supported platform pages (default OFF) |
| 89 | + |
| 90 | +### Default Behavior |
| 91 | + |
| 92 | +- Supported platforms (11+ platforms defined in capture-patterns.ts): Demo Mode automatically enables masking and detection, unaffected by toggles |
| 93 | +- Non-supported platforms: Only enabled when corresponding toggle is ON |
| 94 | + |
| 95 | +### Decision Functions |
| 96 | + |
| 97 | +| Function | Logic | |
| 98 | +|----------|-------| |
| 99 | +| `shouldMask(url)` | `isSupportedPlatform(url) \|\| universalMaskingEnabled` | |
| 100 | +| `shouldAutoCapture(url)` | `isSupportedPlatform(url) \|\| universalDetectionEnabled` | |
| 101 | + |
| 102 | +### Storage |
| 103 | + |
| 104 | +Stored in `chrome.storage.local` with keys `universalMasking` and `universalDetection`. |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## Generic Key Pattern |
| 109 | + |
| 110 | +| Property | Value | |
| 111 | +|----------|-------| |
| 112 | +| Pattern ID | `generic-key` | |
| 113 | +| Confidence | 0.50 | |
| 114 | +| Prefix | `""` (empty string) | |
| 115 | +| Match rule | Common prefixes (key-, token-, api-, secret-, sk-, pk-, rk-) + 30+ alphanumeric chars | |
| 116 | +| Special handling | `KEY_PREFIXES` filters empty string prefix to prevent `containsFullKey()` false positives | |
| 117 | + |
| 118 | +This pattern captures API keys on non-supported platforms, used in conjunction with Universal Detection. Since confidence is 0.50 (medium tier), it triggers the confirmation dialog. |
| 119 | + |
| 120 | +--- |
| 121 | + |
| 122 | +## IPC Flow Diagram (Medium-Confidence Key) |
| 123 | + |
| 124 | +``` |
| 125 | +Content Script Background SW Core Engine |
| 126 | + | | | |
| 127 | + | Key detected (0.35~0.7) | | |
| 128 | + | Mask plaintext | | |
| 129 | + | Show confirmation dialog | | |
| 130 | + | | | |
| 131 | + | [User clicks Confirm] | | |
| 132 | + | | | |
| 133 | + |-- submit_captured_key ------->| | |
| 134 | + | {key, serviceName} | | |
| 135 | + | |-- submit_captured_key -->| |
| 136 | + | | {key, serviceName} | |
| 137 | + | | | |
| 138 | + | |<-- key_stored ----------| |
| 139 | + | | {keyId, masked} | |
| 140 | + |<-- key_stored ---------------| | |
| 141 | + | | | |
| 142 | + | Show toast | | |
| 143 | +``` |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## New Message Types |
| 148 | + |
| 149 | +| Type | Direction | Payload | Description | |
| 150 | +|------|-----------|---------|-------------| |
| 151 | +| `submit_captured_key` | Content -> BG -> Core | `{ key: string, serviceName: string, platform: string }` | Submit captured key | |
| 152 | +| `key_stored` | Core -> BG -> Content | `{ keyId: string, masked: string }` | Key stored confirmation | |
| 153 | +| `get_universal_settings` | Popup -> BG | `{}` | Get universal toggle states | |
| 154 | +| `set_universal_settings` | Popup -> BG | `{ masking: boolean, detection: boolean }` | Set universal toggles | |
| 155 | +| `universal_settings_changed` | BG -> Content | `{ masking: boolean, detection: boolean }` | Broadcast toggle state changes | |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +## File Changes Table |
| 160 | + |
| 161 | +| File | Changes | |
| 162 | +|------|---------| |
| 163 | +| `packages/chrome-extension/src/content/masker.ts` | Three-tier confidence routing, confirmation dialog UI, queue mechanism, rejectedKeys | |
| 164 | +| `packages/chrome-extension/src/content/confirmation-dialog.ts` | Dialog component: creation, events, countdown, Escape | |
| 165 | +| `packages/chrome-extension/src/content/capture-patterns.ts` | Add `generic-key` pattern | |
| 166 | +| `packages/chrome-extension/src/background/service-worker.ts` | Universal settings storage/broadcast | |
| 167 | +| `packages/chrome-extension/src/popup/popup.ts` | Universal Masking / Detection toggle UI | |
| 168 | +| `packages/chrome-extension/src/popup/popup.html` | Toggle HTML structure | |
| 169 | +| `packages/chrome-extension/src/content/pre-hide.ts` | `turbo:before-render` listener | |
| 170 | +| `packages/chrome-extension/src/content/toast.ts` | Duration changed to 25s | |
0 commit comments