palyrad daemon or the palyra-browserd automation service to interact with the user’s real browser for actions like capturing page snapshots, handling selection-based context, or automating tab management.
Architecture and Relay Flow
The extension operates by listening for specific triggers and relaying data to a local loopback endpoint. Unlike traditional extensions that might communicate with a remote SaaS backend, the Relay Companion is strictly bound tolocalhost to maintain a strong security posture.
Component Interaction
- Background Script (
background.js): Acts as the central orchestrator within the extension. It manages the lifecycle of relay requests and handles communication between the popup, content scripts, and the local daemon. - Content Script (
content_script.js): Injected into web pages to perform DOM analysis, collect visible text, and capture snapshots without materializing large strings in memory unnecessarily. - Popup (
popup.js/popup.html): Provides the user interface for pairing the extension with a local Palyra node and configuring allowlists. - Relay Dispatch: The process of sending captured data (e.g., a page snapshot) to the local daemon’s HTTP loopback interface (typically port 7142).
Relay Data Flow Diagram
The following diagram illustrates the flow of acapture_selection action initiated by the user.
“Relay Action Flow”
Sources: apps/browser-extension/background.js:1-50(), apps/browser-extension/content_script.js:184-208(), apps/browser-extension/popup.js:1-40()
Implementation Details
Supported Relay Actions
The extension supports a specific set of actions defined in the relay protocol. These actions are governed by strict payload limits to prevent resource exhaustion.| Action | Description | Constraints |
|---|---|---|
open_tab | Opens a new tab to a specific URL. | Must match relay_allowlist_prefixes. |
capture_selection | Sends the currently highlighted text on the active page to the daemon. | Capped at MAX_RELAY_SELECTION_BYTES (8KB). |
send_page_snapshot | Captures a DOM snapshot and visible text from the current page. | Capped at MAX_RELAY_PAYLOAD_BYTES (32KB). |
Snapshot Collection (content_script.js)
The collectDomSnapshotCapped and collectVisibleTextCapped functions are the core of the data extraction logic. They use a non-recursive stack-based approach to traverse the DOM, ensuring that even extremely large pages do not cause stack overflows.
Key implementation features:
- Capped Buffers: Uses
createCappedBufferto track byte length during traversal apps/browser-extension/content_script.js#55-62. - UTF-8 Safety: Employs
clampUtf8Bytesto truncate strings without splitting multi-byte UTF-8 characters apps/browser-extension/content_script.js#11-32. - Memory Efficiency: Avoids
outerHTMLorinnerTextto prevent the browser from materializing massive strings in the JS heap before the extension can truncate them apps/browser-extension/tests/content_script.test.mjs#156-165.
Security Posture
The extension implements several security layers to protect the user’s browsing data:- Loopback-Only Binding: The
normalizeRelayBaseUrlfunction strictly enforces that the relay target is a loopback address (127.0.0.1orlocalhost) apps/browser-extension/lib.mjs#1-15. - Token Non-Persistence: Sensitive relay tokens are intended to be ephemeral or manually configured via the UI; the extension does not support automated remote provisioning of credentials.
- URL Validation: The
validateOpenTabUrlfunction prevents “username/password” confusion attacks (e.g.,https://google.com@evil.com) and ensures URLs match user-defined prefixes apps/browser-extension/lib.mjs#40-65. - Content Security Policy (CSP): The extension’s manifest restricts script execution and connection targets to ensure no data leaks to third-party domains.
Code Entity Mapping
The following diagram maps the logical browser extension concepts to their specific implementation entities in the codebase. “Extension Entity Map” Sources:apps/browser-extension/manifest.json:1-30(), apps/browser-extension/lib.mjs:1-100(), apps/browser-extension/content_script.js:98-182()
Pairing and Relay Flow
To connect the extension to a Palyra node, the user must perform a pairing flow:- Configure Base URL: In the extension popup, the user sets the
relay_base_url(e.g.,http://127.0.0.1:7142). - Provide Relay Token: A token generated by the
palyraddaemon must be entered into the extension. This token is included in theAuthorization: Bearer <token>header of every relay request. - Prefix Allowlist: The user defines which URL prefixes are allowed for the
open_tabaction to prevent malicious agents from navigating the user’s browser to arbitrary sites.
Configuration Constants
The following constants incrates/palyra-browserd/src/lib.rs define the limits that the daemon expects from the extension:
MAX_RELAY_EXTENSION_ID_BYTES: 96 crates/palyra-browserd/src/lib.rs#157-157MAX_RELAY_SELECTION_BYTES: 8,192 (8KB) crates/palyra-browserd/src/lib.rs#158-158MAX_RELAY_PAYLOAD_BYTES: 32,768 (32KB) crates/palyra-browserd/src/lib.rs#159-159
apps/browser-extension/popup.js:1-50(), crates/palyra-browserd/src/lib.rs:157-159()