github h4ckf0r0day/obscura v0.2.5

2 hours ago

v0.2.5

This release focuses on MCP automation, storage correctness, and browser compatibility. It adds actionable snapshots, preserves tab runtimes, implements IndexedDB transactions, and fixes binary request interception. 128 commits since v0.2.4.

Highlights

  • MCP snapshots include references agents can act on directly. Snapshots return accessible names, live control states, visible text, and bounded element descriptions. Stale references are rejected before an action reaches the wrong element (#1268, #1273).
  • MCP evaluations return completed results and real errors. Returned promises are awaited, scripts execute once, and exceptions, rejections, and timeouts produce tool errors. Active pages continue processing timers and network callbacks between requests (#1227, #1269, #1272).
  • Switching MCP tabs preserves page state. JavaScript globals, event listeners, frame state, and pending promises remain alive until the tab closes (#1274).
  • Storage retains data across more workflows. Web Storage survives navigation and target switching, MCP restores state into its declared origins, and IndexedDB transactions retain records and roll back aborted writes (#1252, #1259, #1270).
  • Iframe loading follows document lifecycle more closely. Fetched frames finish their author scripts before the element’s load event. iframe srcdoc loads in a native child document with inherited base URLs and sandbox restrictions (#1265, #1276).
  • Long-running servers gain worker recycling. Workers can be replaced by connection count, age, or Linux RSS limits. Replacements start before old workers drain their existing connections (#1211).

Rust API change

InterceptResolution::Continue.body is now Option<Vec> instead of Option. For owned text, replace Some(text) with Some(text.into_bytes()).

None preserves the original request body. Some(Vec::new()) replaces it with an empty body. CDP clients continue sending base64-encoded postData; the wire format is unchanged (#874).

Security

  • Rustls is updated from 0.23.45 to 0.23.46, addressing RUSTSEC-2026-0346 through RUSTSEC-2026-0349. The dependency audit passes without additional advisory exceptions (#1261).

MCP and agent automation

  • browser_snapshot includes actionable references, accessible names, control states, and visible body text. Control descriptions and body text share the default 4,000-character content budget; URL and title are capped separately. Password values are omitted (#1273).
  • Snapshots and element listings use the existing native accessibility logic shared with CDP, including labels, ARIA naming, and visibility filtering (#1273).
  • Element references identify the original native node. Copying attributes to a replacement or clone no longer transfers a reference. New listings invalidate previous reference generations (#1268).
  • browser_evaluate accepts scripts, executes them once, and awaits returned promises. Synchronous execution, promise settlement, and result serialization are bounded. JavaScript failures return isError: true rather than successful null or error-string results (#1227, #1272).
  • browser_wait_for_function provides predicate-based waiting with timeout and polling options (#1227).
  • Active pages process timers, network callbacks, and pending navigation between requests over both stdio and HTTP. Idle pages park on browser wakeups (#1269).
  • Tab switching retains live runtimes instead of destroying and recreating page state. Closing a tab still releases its runtime and frames (#1274).
  • Storage-state import restores localStorage into each declared origin, including before navigation. Session storage remains scoped to the active tab. Export includes previously visited stored origins (#1270).
  • browser_fill_form stops before submission if a field fails and completes queued submit navigation before replying. Earlier field changes are not rolled back (#1272).
  • Render-enabled MCP accepts repeatable --font-dir options for screenshots and PDF output. Font directories load before either transport starts (#1235).
  • Graceful MCP shutdown uses the existing cookie and profile persistence path (#1238).

CDP and automation

  • Fetch.continueRequest decodes base64 postData into raw bytes. JSON, binary, and explicitly empty overrides reach the server without string conversion. Invalid binary parameters leave the request paused so a corrected command can resume it (#874).
  • Fetch interception pauses only requests matching the configured Fetch.enable patterns (#1117).
  • Runtime.callFunctionOn accepts object-handle arguments used by go-rod, and DOM.getOuterHTML resolves objectId arguments (#1221).
  • Page.close handles top-level beforeunload confirmation after native user activation. Target.closeTarget remains a force-close (#1221).
  • Page.stopLoading cancels held document, parser-script, and pending rendering-resource loads instead of only acknowledging the command. Canceled navigations do not emit successful load events (#1221).
  • History navigation uses the current preload-script list. Removing an unknown or already-removed preload identifier returns an error (#1215).
  • Page.setBypassCSP is acknowledged during client setup, allowing Playwright contexts configured with bypass_csp to open pages (#1225, #1229).
  • JSON worker navigation accepts per-request load, domcontentloaded, networkidle0, and networkidle2 readiness modes. Invalid modes return an error without navigating (#1127).
  • Color-scheme emulation reaches matchMedia(), CSS selection, screenshots, and PDF layout. Overrides persist across navigation and apply to child documents (#1205).

Storage and runtime

  • localStorage belongs to the browser context and sessionStorage to the tab, both separated by origin. Navigation and CDP target switching no longer discard them. --storage-dir persists localStorage across process runs (#1252).
  • Failed profile writes and removals remain pending for retry. Restored profiles are validated before replacing live state, and Web Storage preserves unpaired UTF-16 units (#1252).
  • IndexedDB uses context-owned, origin-isolated storage. Transactions stage changes and commit atomically; aborts roll back records, schema changes, and generated keys (#1259).
  • IndexedDB supports typed keys and ranges, cloned values, unique and multiEntry indexes, cursors, readonly enforcement, upgrade blocking, and cross-document version-change delivery. Retained data and pending writes are quota-bounded (#1259).
  • Module roots, dependencies, and dynamic imports retain real response metadata and bounded response bodies. Suspending a runtime preserves those bodies without re-encoding them (#1199).
  • Failed module requests produce network-failure records instead of disappearing from request history (#1262).
  • Network errors include their underlying cause chain (#1219).
  • Expired resource-cache entries are removed from eviction bookkeeping (#1202).

DOM, JavaScript, and rendering

  • Document.cloneNode() preserves document metadata, namespaces, templates, and live form-control state without reparsing or modifying the source document (#1275).
  • Attr objects expose their Node interface and support independent cloning. Inert HTML parsing preserves root attributes and document structure without executing scripts (#1275).
  • iframe srcdoc takes precedence over src, including an empty value. Parser input, connected innerHTML, attribute changes, replacement, and removal use the document-loading path (#1276).
  • DOM insertion, replacement, Range mutations, and mutation-observer records follow document constraints, sibling relationships, namespace handling, and requested old-value behavior more closely (#1266).
  • Nested CSS grouping rules are exposed, CSSOM edits invalidate computed styles, and detached elements return empty computed declarations (#1266).
  • Repeated non-geometric computed-style reads reuse ancestor cascades within an unchanged JavaScript task. Style-only paths avoid unnecessary layout and inherited custom-property copies (#1260, #1263).
  • DOM mutations avoid cloning unused node data and allocating rendering bookkeeping that cannot be consumed (#1267).
  • Block children stack correctly inside auto-width inline-blocks, and formatting whitespace no longer distorts their intrinsic width (#1266).
  • word-spacing affects text measurement, layout, and paint. Ordinary non-replaced inline boxes ignore transforms as required by CSS (#955, #1033).
  • HTMLIFrameElement has its own interface identity instead of aliasing every element (#1243).
  • FileList is exposed globally, fixing scripts that previously failed when referencing it (#1233).
  • Plain-text and Markdown responses produce literal-text documents. document.contentType, leading newlines, empty responses, and metadata reset behavior are preserved (#1234).

Server operation

  • Worker recycling supports --worker-max-connections, --worker-max-rss, --worker-max-age, and --worker-drain-timeout. RSS-based recycling is Linux-only, and recycling requires multiple workers (#1211).
  • Multiworker serve handles SIGTERM and SIGINT and shuts down its children. --max-connections is forwarded and enforced per worker (#1213).
  • Linux/glibc workers can return freed heap memory while other connections remain active. Busy-worker trimming is coordinated to avoid concurrent allocator pauses (#1209).
  • scrape and batch fetch keep spawned jobs within --concurrency and preserve input order. URL input and completed results remain buffered (#1203).

Packaging and validation

  • CLI and MCP builds from tagged source archives report the release version instead of falling back to the workspace version (#1255).
  • CI detects incomplete V8 native-library caches and rebuilds the affected dependency without discarding healthy caches (#1253).
  • Performance smoke measurements use immediate process-exit timing rather than timeout polling that distorted short runs (#1264).
  • Stealth regression coverage includes scripted network events and retained response bodies (#1130).
  • Final main passed 2,332 render tests with five existing skips, 1,394 no-render workspace tests with three existing skips, 31 library tests, and the stealth networking checks.
  • All four release build configurations passed: render, render+stealth, no-render, and no-render+stealth.
  • The final main obstacle course passed all 33 stages.
  • Additional storage validation included the upstream TodoMVC suite: Chromium 24/24 and Obscura 24/24, with unchanged test bodies and the existing CDP connection adapter. This is not a claim of complete Playwright compatibility.

Contributors

Thanks to @Suydev, @Yi-111-a, @anandmahadevv, @flolep2607, @fwonce, @ginkel, @ice-zeus, @lisa0314, @ntdatt812, @pederbe, @seamile, @vvinayakkk, @wstczyw, and @yvv4git for contributions to this release.

Full Changelog: v0.2.4...v0.2.5

Don't miss a new obscura release

NewReleases is sending notifications on new releases.