From 8f50811aa79f921b3b9366f0967b874976ad9eb6 Mon Sep 17 00:00:00 2001 From: Jacek Wielemborek Date: Sat, 25 Oct 2025 20:53:42 +0200 Subject: [PATCH] feat(verify): use browser.storage as execution proof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debugger port doesn't prove extension code executed (Firefox opens it). New approach: - Extension writes marker to browser.storage.local on init - Test script checks Firefox profile for storage.js file - Verifies _rentgen_init_timestamp and _rentgen_init_iso keys This proves: - background.ts executed - browser.storage.local.set() succeeded - Extension has working browser API access Non-invasive: storage is only used for automated tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- background.ts | 13 +++++++ scripts/test_verify.py | 86 ++++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 40 deletions(-) diff --git a/background.ts b/background.ts index 4e2e800..4027e55 100644 --- a/background.ts +++ b/background.ts @@ -1,3 +1,16 @@ import { init } from "./memory"; +// Use global browser object directly (available in extension context) +declare const browser: any; + init(); + +// Set storage marker for test verification (non-invasive, only for automated tests) +if (typeof browser !== 'undefined' && browser.storage) { + browser.storage.local.set({ + '_rentgen_init_timestamp': Date.now(), + '_rentgen_init_iso': new Date().toISOString() + }).catch(() => { + // Silently fail if storage API not available + }); +} diff --git a/scripts/test_verify.py b/scripts/test_verify.py index ecf28de..96b1a15 100755 --- a/scripts/test_verify.py +++ b/scripts/test_verify.py @@ -118,28 +118,41 @@ def check_javascript_errors(log_path: Path) -> list[str]: return errors -def check_debugger_port(log_path: Path) -> str | None: - """Extract debugger port from logs. Returns port number or None.""" - content = log_path.read_text() - - import re - match = re.search(r"start-debugger-server (\d+)", content) - if match: - return match.group(1) - return None - - -def test_debugger_connectivity(port: str) -> bool: - """Test if remote debugging protocol is accessible.""" +def check_extension_storage() -> tuple[bool, str]: + """Check if extension wrote initialization marker to browser.storage. + Returns (success, message).""" try: - result = subprocess.run( - ["timeout", "2", "bash", "-c", f"echo > /dev/tcp/127.0.0.1/{port}"], - capture_output=True, - timeout=3 - ) - return result.returncode == 0 - except (subprocess.TimeoutExpired, subprocess.SubprocessError): - return False + # Query Firefox profile for extension storage + # Extension storage is in: /browser-extension-data//storage.js + import glob + import json + + # Find Firefox profile created by web-ext + profiles = glob.glob("/tmp/tmp-*-*-rentgen@*") + if not profiles: + return False, "No Firefox profile found" + + profile = profiles[0] + storage_pattern = f"{profile}/browser-extension-data/*/storage.js" + storage_files = glob.glob(storage_pattern) + + if not storage_files: + return False, "No storage.js file found in profile" + + # Read storage file + with open(storage_files[0], 'r') as f: + storage_data = json.load(f) + + # Check for our marker keys + if '_rentgen_init_timestamp' in storage_data and '_rentgen_init_iso' in storage_data: + timestamp = storage_data['_rentgen_init_timestamp'] + iso = storage_data['_rentgen_init_iso'] + return True, f"Extension initialized at {iso} (timestamp: {timestamp})" + + return False, "Storage marker not found" + + except Exception as e: + return False, f"Storage check failed: {e}" def cleanup(xvfb_pid: int, webext_pid: int) -> None: @@ -196,31 +209,24 @@ def main() -> int: # Functional test: Verify extension code execution print_header("Functional test: Verifying extension code execution...") - port = check_debugger_port(log_path) + execution_verified, message = check_extension_storage() - # Guard: Check if debugger port found - if not port: - print_error("Could not find debugger port in logs") + # Guard: Check if we found proof of execution + if not execution_verified: + print_error("Could not verify extension code execution") + print_error(f"Reason: {message}") print_error("Extension installed but NO PROOF of code execution") cleanup(xvfb_pid, webext_pid) return 1 - print_success(f"Firefox debugger port: {port}") - - # Guard: Check debugger connectivity - if not test_debugger_connectivity(port): - print_error("Remote debugging not accessible") - print_error("Extension installed but CANNOT VERIFY code execution") - cleanup(xvfb_pid, webext_pid) - return 1 - - print_success("Remote debugging protocol accessible") - print_success("Extension code VERIFIED executing") + print_success("Extension code VERIFIED executing!") print() - print("NOTE: Verified by:") - print(" - Extension installed without errors") - print(" - Background page loaded (debugger accessible)") - print(" - No JavaScript errors detected") + print(f"Proof: {message}") + print() + print("This proves:") + print(" - background.ts executed") + print(" - browser.storage.local.set() succeeded") + print(" - Extension has working browser API access") # Show process info print()