f7fc15b17c
Includes: - cli.py path fix (parents[1]) for config/catalog resolution - Library cleanup feature design docs (TODO.md, mockup) - Audit + bug-queue markdowns from May 2026 reliability pass - .gitignore expanded for transient artifacts
98 lines
7.2 KiB
Markdown
98 lines
7.2 KiB
Markdown
# Candidate Findings — Extension Popup + Bulk Check — audit-snapshot-2026-05-24T15-55Z.md
|
|
|
|
Scope: src/popup/* + src/bulk-check/* + src/shared/id-extract.js
|
|
Required-reading: ext AGENTS.md / bug-audit-plan.md
|
|
Auditor: fresh Explore agent (Phase 1 audit)
|
|
|
|
## Candidate C-1: Popup closes before open-bulk-check message completes
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:563-565`
|
|
- **Hunch:** Popup window closes immediately after sending `open-bulk-check` message without callback, risking message loss if popup is killed before IPC serialization.
|
|
- **Trace:** Line 564 sends message with NO callback, line 565 immediately closes popup.
|
|
- **Question for verifier:** Does Chrome guarantee sendMessage() is queued before window.close() returns?
|
|
- **Contract refs needed:** Chrome Runtime API message passing guarantees
|
|
|
|
## Candidate C-2: Delete confirmation allows stale expectedId from prior modal session
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:318-372`
|
|
- **Hunch:** Global `expectedId` set when hit is selected. If modal closes without selection and reopens, old `expectedId` persists and could allow false-positive match.
|
|
- **Trace:** `expectedId` is global line 316, set in selectHit() line 353, but NOT reset in openDeleteModal().
|
|
- **Question for verifier:** Can modal open without selecting a hit, leaving stale `expectedId` that allows unintended validation?
|
|
- **Contract refs needed:** Modal state management
|
|
|
|
## Candidate C-3: Manual search captures t0 before SW eviction, causing misleading timings
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:452-470`
|
|
- **Hunch:** `t0 = performance.now()` captured at send time. If SW evicted/restarted during 90s timeout, callback fires with unbounded `total_ms`.
|
|
- **Trace:** Lines 452 and 468 show t0 captured and used to synthesize total_ms after callback.
|
|
- **Question for verifier:** When SW dies mid-request, can callback fire with unbounded total_ms contradicting host query time?
|
|
- **Contract refs needed:** SW lifecycle, AGENTS.md timeout handling
|
|
|
|
## Candidate C-4: History chip click executes search without checking modal state
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:423-425`
|
|
- **Hunch:** History chip click calls runManualSearch() unconditionally. If delete modal open with chosenHit, search executes while modal remains visible with stale state.
|
|
- **Trace:** Line 425 calls runManualSearch() with no check for open modals.
|
|
- **Question for verifier:** Should clicking history chip close delete modal first?
|
|
- **Contract refs needed:** Modal lifecycle specification
|
|
|
|
## Candidate C-5: Search Clear button does not close delete modal
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:479-484`
|
|
- **Hunch:** Clear button resets manualMode and calls runCheck() but does NOT close delete modal, leaving it open with stale chosenHit.
|
|
- **Trace:** Lines 479-484 show no $overlay.style.display = "none"
|
|
- **Question for verifier:** If user opens delete modal then clicks Clear, does modal remain open in invalid state?
|
|
- **Contract refs needed:** Modal lifecycle specification
|
|
|
|
## Candidate C-6: Bulk-check uses innerHTML with escaped fields (fragile pattern)
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\bulk-check\bulk-check.js:26-44`
|
|
- **Hunch:** All template fields are escaped currently, but innerHTML pattern is fragile. If future code adds unescaped response fields, XSS possible.
|
|
- **Trace:** Lines 32-44 show escapeHtml() called on fields, but innerHTML assignment could miss new fields.
|
|
- **Question for verifier:** Are all response fields (e.g., cache_meta, scanned_remotes) properly escaped?
|
|
- **Contract refs needed:** XSS contract, host response schema
|
|
|
|
## Candidate C-7: Profile selector change triggers search without canceling in-flight request
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:612-622`
|
|
- **Hunch:** Profile change triggers new search without AbortController. Old search callback could fire after new one, rendering stale (old-profile) results.
|
|
- **Trace:** Lines 620-621 call runManualSearch/runCheck with no request ID or AbortController.
|
|
- **Question for verifier:** If user changes profiles while search in-flight, can old callback render stale results?
|
|
- **Contract refs needed:** Message passing race condition contract
|
|
|
|
## Candidate C-8: Bulk-check does not warn when query count exceeds 250-query limit
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\bulk-check\bulk-check.js:13-18`
|
|
- **Hunch:** readBulkIds() deduplicates but does NOT enforce 250-query limit. User pastes 300 IDs, UI shows "300 unique IDs", host silently truncates to 250.
|
|
- **Trace:** No limit enforcement in readBulkIds(). Host limit at rcjav-host.py line 818: queries[:250]
|
|
- **Question for verifier:** Should UI warn when input exceeds 250 IDs?
|
|
- **Contract refs needed:** Host bulk_search limit contract
|
|
|
|
## Candidate C-9: Undo modal button success feedback only visible for 1.2 seconds
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:536-543`
|
|
- **Hunch:** Button text changes to "✓ restored" but modal auto-closes after 1.2s. May be too brief for user to see success state.
|
|
- **Trace:** Line 536 sets button text to checkmark, line 541 closes modal after only 1200ms timeout.
|
|
- **Question for verifier:** Is 1.2s timeout intentional, or should success state remain visible longer?
|
|
- **Contract refs needed:** Undo UX specification
|
|
|
|
## Candidate C-10: Cache banner age uses Math.round, hiding near-boundary staleness
|
|
- **File:** `D:\DEV\Extensions\Production\rclone-jav\src\popup\popup.js:604`
|
|
- **Hunch:** Math.round(24.4) = 24, making 24.4h cache appear as 24h old. Should use Math.ceil for conservative rounding.
|
|
- **Trace:** Line 604 uses Math.round() on oldest.age_hours
|
|
- **Question for verifier:** Should cache age always round up to conservatively display staleness?
|
|
- **Contract refs needed:** Cache freshness display contract
|
|
|
|
---
|
|
|
|
## Summary: 10 candidates found
|
|
Most critical: C-1 (message race), C-2 (stale state), C-7 (search race)
|
|
|
|
---
|
|
|
|
## VERIFIER NOTES (Phase 1 Moderate verification, stricter prompt + UI-lifecycle rule + bulk-check window awareness)
|
|
|
|
- C-1 (open-bulk-check race) — REFUTED. Chrome runtime guarantees fire-and-forget delivery before sender unload.
|
|
- C-2 (stale expectedId) — PARTIAL → demoted M to L. Delete RPC uses chosenHit (reset every open); typing-validation just gates UI button; no wrong-delete possible. Promoted as L-1.
|
|
- C-4 (history chip during modal) — PARTIAL → demoted M to L. chosenHit is reference; delete still correct file. Cosmetic UI confusion only. Promoted as L-2.
|
|
- C-5 (Clear button modal) — CONFIRMED M, high confidence. Modal stays open; no Esc handler; delete still works but UX broken. Promoted as M-1.
|
|
- C-7 (profile selector race) — CONFIRMED M, high confidence. Real race, stale results stick. Promoted as M-2.
|
|
|
|
CHUNK 5 CALIBRATION:
|
|
- Severe: 0 (none flagged)
|
|
- Moderate raw rejection: 1/5 pure REFUTED, 2/5 demoted = 60% downgrade rate
|
|
- Combined: stop condition triggered
|
|
- Auditor weaknesses: flagging timing races without checking (a) platform contracts, (b) object reference vs rebuilt-from-current-results, (c) self-correcting cosmetic-only effects
|
|
- L candidates NOT verified per stop condition. Revisit only if needed.
|