Security Model
OpenDevBrowser Architecture This document describes the architecture of OpenDevBrowser across plugin, CLI, and extension distributions, with a security-first focus. Status: active Last updated: 2026-04-12 System overview
OpenDevBrowser Architecture
This document describes the architecture of OpenDevBrowser across plugin, CLI, and extension distributions, with a security-first focus.
Status: active
Last updated: 2026-04-12
System overview
OpenDevBrowser provides four primary runtime entry points:
- Plugin: OpenCode runtime entry that exposes
opendevbrowser_*tools. - CLI: Installer + automation commands (daemon or single-shot
run), plus guarded internalrpcpassthrough for power users (unsafe, use with caution). - Extension: Relay mode for attaching to existing logged-in tabs.
- Website (private repo): Next.js website and generated docs viewer maintained in
opendevbrowser-website-deploy/frontend/. - Hub daemon:
opendevbrowser serveprocess that owns the relay and enforces FIFO leases when hub mode is enabled. - Automation platform layer: provider runtime, macro resolver, tiered fingerprint controls, and combined debug trace workflows shared across tool/CLI/daemon surfaces.
Current automation surface sizes:
- CLI commands:
77 - Plugin tools:
70 /opscommand names:59/canvascommand names:35
Human-facing inventory metadata now composes through one generated manifest:
src/public-surface/source.tsowns the canonical public CLI command, tool, and CLI-tool pair metadatascripts/generate-public-surface-manifest.mjsregenerates the public manifest snapshotssrc/public-surface/generated-manifest.tsand.jsonare the consumed inventory mirrors for runtime help, docs parity, and testssrc/cli/onboarding-metadata.jsonowns the canonical first-contact skill, topic, quick-start commands, and onboarding doc pointerssrc/cli/help.ts,src/cli/args.ts, andsrc/tools/index.tsconsume or re-export the generated manifest for human-facing command and tool inventory outputsrc/cli/help.tsalso owns the first-contactFind It Fastblock forscreencast / browser replay,desktop observation, and the browser-scoped computer-use lane surfaced through--challenge-automation-mode- Additive operator pairings stay inside the existing families:
status-capabilities->status.capabilities,review-desktop->nav.reviewDesktop,session-inspector-plan->session.inspectPlan, andsession-inspector-audit->session.inspectAudit docs/SURFACE_REFERENCE.mdmirrors every public CLI command and tool name with those short descriptionsdocs/CLI.mdcarries the longer operator guide and help parity runbooksrc/tools/index.tsremains the runtime tool registry authority
The shared runtime core is in src/core/ and wires BrowserManager, CanvasManager, AnnotationManager, AgentInbox, ScriptRunner, SkillLoader, and RelayServer.
CanvasManager lives in src/browser/canvas-manager.ts and composes dedicated session-sync, code-sync, starter-catalog, and runtime-preview bridge helpers while delegating document, export, framework-adapter, library-adapter, plugin, starter, kit, and token primitives to src/canvas/ plus deterministic Figma import helpers under src/integrations/figma/.
Daemon-backed canvas CLI requests inject the caller worktree as repoRoot; CanvasManager persists that root per canvas session so relative document saves, exports, imported asset materialization, and code-sync manifest/source paths resolve against the caller repo instead of the daemon process cwd.
AgentInbox provides repo-local, chat-scoped delivery for popup/canvas annotation sends and the shared annotate --stored retrieval path.
Canonical inventory and channel contracts: docs/SURFACE_REFERENCE.md.
Frontend architecture and generation flow are documented in docs/FRONTEND.md.
The CLI installer reconciles daemon auto-start after every successful install
(macOS LaunchAgent, Windows Task Scheduler). Existing per-user entries are rechecked and repaired when they are missing or stale on
supported platforms, and when the macOS LaunchAgent is malformed; unsupported platforms are skipped and continue without auto-start. If the current CLI entrypoint is running from a
transient temp-root path, install-time reconciliation refuses to persist it and surfaces guidance to rerun daemon install from a
stable install location. getAutostartStatus() remains the canonical source of auto-start truth for both install reconciliation
and daemon status, and a stable persisted auto-start entry remains authoritative even when the current invocation is transient.
Challenge orchestration ownership
The anti-bot cutover keeps blocker truth and challenge lifecycle separate on purpose:
src/browser/session-store.tsremains the only blocker FSM authority.src/browser/browser-manager.tsandsrc/browser/ops-browser-manager.tsremain the only writers of surfaced blocker and challenge metadata. Existingmeta.blocker,meta.blockerState, andmeta.blockerResolutionfields stay stable; additivemeta.challengeandmeta.challengeOrchestrationare layered on top, and the publicreviewsurface composes that manager status with a fresh actionables capture before action.src/browser/global-challenge-coordinator.tsowns lifecycle-only state for claim, refresh, resolve, defer, expire, and release. It does not classify blockers.src/challenges/is the shared Part 2 intelligence plane. It builds canonical evidence, interprets the incident, selects one bounded lane, executes browser-native steps, verifies via manager-owned checks, and emits reclaimable yield or outcome records without becoming a second truth authority.src/providers/runtime-factory.tsplussrc/providers/browser-fallback.tsown preserve-or-complete browser fallback transport. Responses use explicitdispositionvalues:completed,challenge_preserved,deferred, andfailed.src/providers/registry.tsis the sole durable anti-bot pressure authority.src/providers/shared/anti-bot-policy.ts,src/providers/policy.ts,src/providers/index.ts, andsrc/providers/workflows.tsread or write that registry-backed state instead of maintaining parallel durable maps.- Provider modules keep extraction logic and
recoveryHints()only. Shared runtime owns fallback ordering, preserve or resume decisions, and legacy compatibility translation for older fallback callers.
Legitimacy boundary:
- In scope: preserved sessions, standard browser controls, bounded auth-navigation and session-reuse attempts, bounded interaction experimentation, reclaimable human yield for secret or human-authority boundaries, and owned-environment challenge fixtures that use vendor test keys only.
- Out of scope: hidden bypasses, CAPTCHA-solving services, token harvesting, or autonomous unsandboxed solving of third-party anti-bot systems.
Challenge automation override contract
- Public override field:
challengeAutomationMode - Accepted values:
off,browser,browser_with_helper - Effective precedence:
run > session > config - Generated help and docs surface this as the browser-scoped computer-use lane; it is intentionally not a desktop-agent or desktop-command family.
- Config baseline:
providers.challengeOrchestration.mode BrowserManagerandOpsBrowserManagerremain the only surfaced challenge metadata writers.meta.challengeOrchestrationand fallbackdetails.challengeOrchestrationcan exposemode,source,standDownReason, and helper eligibility so stand-down decisions stay explicit.- The optional helper bridge is browser-scoped, not a desktop agent.
browserdisables it, whilebrowser_with_helperonly evaluates it when the existing hard gates pass. - Shipped builds keep desktop entitlement separate under
desktop.*; that sibling runtime is never granted bychallengeAutomationMode. - Governed advanced lanes stay separately entitlement-gated and are never granted by
challengeAutomationMode.
Roadmap-only desktop boundary
This section is roadmap-only for any public desktop-agent claim. Shipped builds now include a public read-only desktop observation plane over the sibling desktop runtime contract plus a top-level automation coordinator, but desktop-agent behavior remains non-public and observation-only while the shipped observation default can still be opted out through desktop.permissionLevel=off.
- The shipped sibling runtime already uses a separate contract from
ChallengeRuntimeHandle,BrowserManagerLike, and/ops; any future public desktop agent must preserve that separation. - Core composition creates
desktopRuntimebesideBrowserManagerandOpsBrowserManager, then exposes a non-publicobserveDesktopAndVerifyentrypoint that routes desktop observation back through browser-owned review before surfacing completion. - Minimum capability bar before any desktop-agent claim is allowed:
- OS-level input actuation outside the browser
- cross-window and cross-app focus management
- desktop capture or accessibility-tree observation beyond browser DOM
- explicit permission and consent gating
- bounded workspace and abort controls
- audit artifacts and replay-safe execution logs
- a typed failure taxonomy separate from the current helper bridge
- Public docs and surfaces may describe the shipped read-only desktop observation plane, but they must not describe the current helper bridge as a desktop agent or imply that
/opsis a desktop control channel.
Component map
Canonical ASCII map
┌─────────────────────────────────────────────────────────────────┐
│ Distribution Layer │
├──────────────────┬──────────────────┬──────────────────┬──────────────────────────┤
│ OpenCode Plugin │ CLI │ Hub Daemon │ Chrome Extension │
│ (src/index.ts) │ (src/cli/index) │ (opendevbrowser │ (extension/src/) │
│ │ │ serve) │ │
└────────┬─────────┴────────┬─────────┴─────────┬────────┴──────────────┬────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Core Runtime (src/core/) │
│ bootstrap.ts → wires managers, sibling desktop runtime, │
│ automation coordinator, injects ToolDeps │
└────────┬────────────────────────────────────────────────────────┘
│
┌────┴────┬─────────────┬──────────────┬──────────┬────────────┬────────────┬────────────┐
▼ ▼ ▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐ ┌────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│Browser │ │Script │ │Snapshot │ │ Canvas │ │ Annotation │ │ Relay │ │ Skills │
│Manager │ │Runner │ │Pipeline │ │Manager │ │ Manager │ │ Server │ │ Loader │
└───┬────┘ └────────┘ └──────────┘ └────┬───┘ └────────────┘ └─────┬──────┘ └────────────┘
│ │
▼ ▼
┌────────┐ ┌────────────┐
│Target │ │ Extension │
│Manager │ │ (WS relay) │
└────────┘ └────────────┘
Data flow
Tool Call → Zod Validation → Manager/Runner → CDP/Playwright → Response
↓
Snapshot (AX-tree → refs)
↓
Action (ref → backendNodeId → DOM)
Detailed dependency map (Mermaid)
flowchart LR
subgraph Distribution
Plugin[OpenCode Plugin]
CLI[CLI]
Hub[Hub Daemon]
Extension[Chrome Extension]
Frontend[Private Website Repo]
end
subgraph HubProxy[CLI Hub Proxy]
DaemonClient[DaemonClient]
RemoteManager[RemoteManager]
RemoteCanvasManager[RemoteCanvasManager]
RemoteRelay[RemoteRelay Cache]
end
subgraph Core
CoreBootstrap[Core Bootstrap]
BrowserManager[BrowserManager]
TargetManager[TargetManager]
ProviderRuntime[Provider Runtime]
MacroRegistry[Macro Registry]
Fingerprint[Fingerprint Tiers]
CanvasManager[Canvas Manager]
AnnotationManager[AnnotationManager]
AgentInbox[AgentInbox]
ScriptRunner[ScriptRunner]
Snapshotter[Snapshot Pipeline]
Devtools[DevTools Trackers]
Exporter[Export Pipeline]
Relay[RelayServer]
ChallengeCoord[Challenge Coordinator]
DesktopRuntime[Desktop Observation Runtime]
AutomationCoordinator[Automation Coordinator]
end
Plugin --> CoreBootstrap
CLI --> DaemonClient
CLI --> RemoteManager
CLI --> RemoteCanvasManager
RemoteManager --> DaemonClient
RemoteCanvasManager --> DaemonClient
RemoteRelay --> DaemonClient
DaemonClient --> Hub
CLI --> CoreBootstrap
Hub --> CoreBootstrap
Extension --> Relay
Frontend --> CLI
Frontend --> Docs[docs/* + CHANGELOG + skills/*/SKILL.md]
CoreBootstrap --> BrowserManager
BrowserManager --> TargetManager
CoreBootstrap --> CanvasManager
CanvasManager --> BrowserManager
CanvasManager --> Relay
CoreBootstrap --> ProviderRuntime
CoreBootstrap --> MacroRegistry
BrowserManager --> Fingerprint
CoreBootstrap --> AnnotationManager
AnnotationManager --> BrowserManager
CoreBootstrap --> AgentInbox
AnnotationManager --> AgentInbox
AnnotationManager --> Relay
CoreBootstrap --> ScriptRunner
CoreBootstrap --> Snapshotter
CoreBootstrap --> Devtools
CoreBootstrap --> Exporter
CoreBootstrap --> Relay
CoreBootstrap --> ChallengeCoord
CoreBootstrap --> DesktopRuntime
CoreBootstrap --> AutomationCoordinator
ChallengeCoord --> BrowserManager
DesktopRuntime --> AutomationCoordinator
Runtime flows
1) Plugin tool invocation
- OpenCode calls a tool like
opendevbrowser_launch. - Tool validates inputs with Zod and delegates to
BrowserManager. BrowserManagerlaunches or connects to a Chrome instance.- Optional automation flows route through provider runtime (
search/fetch/crawl/post) and macro resolution. - Tool returns structured response with session id, trace-aware diagnostics, and warnings.
2) CLI automation (daemon mode)
sequenceDiagram
actor User
participant CLI
participant Daemon
participant Core
participant Relay
participant Browser
User->>CLI: opendevbrowser serve
CLI->>Daemon: start local server (127.0.0.1) and relay
Note over Daemon,Relay: Hub daemon owns relay + FIFO leases
Daemon->>Core: create core runtime
Core->>Relay: start relay server
User->>CLI: opendevbrowser launch
CLI->>Daemon: POST /command (Bearer token)
Daemon->>Core: session.launch
Core->>Browser: launch or connect
Core-->>Daemon: session id
Daemon-->>CLI: result
User->>CLI: opendevbrowser rpc --unsafe-internal --name <command>
CLI->>Daemon: POST /command (raw internal command name + params, bypasses stable CLI surface)
Daemon-->>CLI: raw command result
rpc is intentionally CLI-only and internal. It can invoke unstable daemon command paths and should be treated as a last-resort power-user interface.
3) Extension relay mode
sequenceDiagram
actor User
participant Extension
participant Hub
participant Relay
participant Browser
participant Tools
User->>Extension: Enable auto-connect
Extension->>Relay: GET /config (extension origin or loopback no-Origin)
Extension->>Relay: GET /pair (extension origin or loopback no-Origin)
Extension->>Relay: WS /extension
Tools->>Relay: GET /config (loopback)
Tools->>Relay: GET /pair (when pairing required, loopback)
Tools->>Hub: acquire binding/lease when required
Tools->>Relay: WS /ops?token=...
Tools->>Relay: WS /canvas?token=... (design canvas relay)
Tools->>Relay: WS /annotation?token=... (annotate relay)
Relay->>Extension: forward ops envelopes
Relay->>Extension: forward canvas envelopes
Extension->>Relay: WS /annotation?token=... (store_agent_payload for popup/canvas sends)
Extension->>Browser: execute CDP/debugger commands
Browser-->>Extension: CDP events/results
Extension-->>Relay: relay events/results
Relay-->>Tools: forward events/results
4) Website docs/content generation (private repo)
sequenceDiagram
participant Sources as docs/* + CHANGELOG + skills/*/SKILL.md
participant Generator as private frontend/scripts/generate-docs.mjs
participant Content as private frontend/src/content/*
participant Next as private frontend/src/app/docs/*
Sources->>Generator: markdown and metadata inputs
Generator->>Content: pages.json + docs-manifest.json + metrics.json + roadmap.json
Next->>Content: render docs gateway and reference routes
Session modes
extension: attach to an existing tab via the Chrome extension relay.managed: launch and manage a Chrome instance via Playwright (headed by default).cdpConnect: attach to an existing Chrome via CDP (/json/version).connectrouting: local relay WS endpoints (for examplews://127.0.0.1:<relayPort>or/ops) are normalized to/opsand routed via the relay (extensionmode). Legacy/cdprequires--extension-legacy.- Launch defaults to
extensionwhen available; managed/CDPConnect require explicit user choice. - Extension relay requires Chrome 125+ and uses flat-session routing with DebuggerSession
sessionId. - Hub mode supports multi-client access.
/opsaccepts multiple clients, while FIFO binding/lease coordination applies to legacy/cdpand protected extension-session command paths.
Relay channel contracts
/opsis the default high-level extension channel with explicit commands (session.*,targets.*,page.*,nav.*,interact.*,dom.*,export.*,devtools.*)./opsenvelopes:ops_hello,ops_request,ops_response,ops_error,ops_event,ops_chunk,ops_ping,ops_pong./canvasis a dedicated design-canvas channel for session handshakes, governance-plan gating, canonical document mutation requests, extension-hosted design-tab editor sync, overlay selection, preview refresh, and feedback events./canvasdesign tabs consume a canonical HTML preview generated in core.canvas.tab.openis the public command; internalcanvas.tab.synckeeps extension-hosted design tabs aligned with the same core-rendered materialization after public mutations. Extension history clicks emit the internalcanvas_eventtypecanvas_history_requested, but the lease-governed mutation still runs through publiccanvas.history.undoorcanvas.history.redo./canvasenvelopes:canvas_hello,canvas_request,canvas_response,canvas_error,canvas_event,canvas_chunk,canvas_ping,canvas_pong./cdpis legacy and forwards raw CDP commands viaforwardCDPCommandenvelopes (id,method,params, optionalsessionId) and relays events/responses back./annotationremains a dedicated channel for annotation command/event/response flow. It carries capture commands (start,cancel), shared stored retrieval (fetch_stored), and extension send delivery (store_agent_payload).- Full command names and payload examples are documented in
docs/SURFACE_REFERENCE.md.
Agent inbox delivery flow
chat.messageandexperimental.chat.system.transformregister activesessionIDvalues as chat scope keys for the current worktree.- Extension popup, canvas, and in-page annotation
Sendactions dispatchannotation:sendPayloadto the extension background, which callsstore_agent_payloadover/annotation. - During core bootstrap, the relay registers a local store handler; that handler calls
AgentInbox.enqueue(...). Shared entries are written under.opendevbrowser/annotate/agent-inbox.jsonl; active scope metadata is stored in.opendevbrowser/annotate/agent-scopes.json. - Shared persistence strips screenshots, keeps asset refs only, and bounds storage to
200entries total,50unread entries,7days TTL, and duplicate suppression within60seconds. experimental.chat.system.transformpeeks only the current scope, injects up to20items or256 KiBof serialized system text, and marks injected items consumed.annotate --storedreads the shared inbox first and falls back to the extension-local stored payload when no shared item is available.
Multi-tab concurrency contract
- Canonical contract:
docs/CLI.md(concurrency semantics) andsrc/config.ts(parallelismsettings). - Execution key:
ExecutionKey = (sessionId, targetId). - Command taxonomy:
TargetScoped:goto,wait,snapshot,review, interaction commands, DOM commands,page.screenshot,page.dialog, export/devtools target-bound commands.SessionStructural: connect/disconnect, target/page create/close/select/list.- Scheduler guarantees:
- Same target: strict FIFO.
- Different targets in one session: parallel up to governor
effectiveParallelCap. - Governor policy source of truth:
src/config.ts(parallelismblock), passed to extension/opsatsession.connect. - Legacy
/cdpremains compatibility-only (effectiveParallelCap=1). - Extension headless is unsupported by contract; headless extension launch/connect intent fails with
unsupported_mode. - Declared intentional mismatches are registry-bound in
docs/PARITY_DECLARED_DIVERGENCES.md; undeclared parity mismatches fail gates.
Automation platform surfaces
- Provider runtime supports source policy routing (
auto|web|community|social|shopping|all) with per-provider timeouts, retries, circuit-breaker state, and partial-success envelopes. - Workflow wrappers expose finalized skill-aligned entrypoints:
research.run/opendevbrowser_research_run/opendevbrowser research runshopping.run/opendevbrowser_shopping_run/opendevbrowser shopping runproduct.video.run/opendevbrowser_product_video_run/opendevbrowser product-video runinspiredesign.run/opendevbrowser_inspiredesign_run/opendevbrowser inspiredesign run- Those workflow wrappers also expose
challengeAutomationMode(off|browser|browser_with_helper) as a run-scoped override withrun > session > configprecedence. - Workflow runtime primitives are layered as:
timebox(strictdays|from|toresolution)orchestrator(source/provider fanout + partial-failure accumulation)enrichment(engagement/recency/date-confidence)renderer(compact|json|md|context|path)artifact writer(owner-only paths, TTL metadata, cleanup support)- Macro engine resolves
@macro(...)expressions into provider operations (src/macros/*) and is exposed through tool/CLI/daemon (macro_resolve,macro-resolve,macro.resolve) with resolve-only and execute modes. - Execute-mode macro responses keep existing shapes and add metadata fields:
meta.tier.selected,meta.tier.reasonCode,meta.provenance.provider,meta.provenance.retrievalPath, andmeta.provenance.retrievedAt. - Diagnostics include a session-first inspection lane (
session.inspect,opendevbrowser_session_inspector,session-inspector) plus console/network/exception trackers and a combined debug bundle endpoint (debug_trace_snapshot,debug-trace-snapshot,devtools.debugTraceSnapshot). - Design canvas surfaces expose
canvas.execute/opendevbrowser_canvas/opendevbrowser canvasand are layered as: session handshake + attach(canvas.session.open,canvas.session.attach,canvas.capabilities.get) for governance, plan requirements, same-user observer joins, explicit lease reclaim,generationPlanRequirements.allowedValues,generationPlanIssues, and runtime-returnedguidance.recommendedNextCommandsdocument store(canvas.document.load,canvas.document.import,canvas.document.patch,canvas.document.save,canvas.document.export) for repo-native JSON artifacts, typed Yjs-backed document state, Figma file or node ingestion, governance completion, save/export policy gates, missing-vs-invalid generation-plan classification, and patch-driven preview re-materializationhistory(canvas.history.undo,canvas.history.redo) for lease-held undo/redo, selection and viewport preimages, no-op-before-first-mutation behavior, deterministic invalidation when external revision drift makes the recorded stack stale, and extension design-tab history controls that emitcanvas_history_requestedbefore public undo/redo executioninventory(canvas.inventory.list,canvas.inventory.insert, plusinventory.promote|update|removepatch ops) for reusable stage-node promotion, document-backed component catalogs, built-in kit catalog inventory, and governed reinsertion onto the active pagestarters(canvas.starter.list,canvas.starter.apply) for built-in starter discovery, automatic generation-plan seeding, kit token merges, required inventory installation, and starter shell materialization with semantic fallback for unsupported framework or adapter requests; starter responses preferlibraryAdapterIdfor the resolved kit adapter while retainingadapterIdas a compatibility alias distinct from code-syncframeworkAdapterIdcode sync(canvas.code.bind,canvas.code.unbind,canvas.code.pull,canvas.code.push,canvas.code.status,canvas.code.resolve) for framework-adapter-backed round-trip bindings, manifest persistence under.opendevbrowser/canvas/code-sync/<documentId>/<bindingId>.json, built-in React/HTML/custom-elements/Vue/Svelte lanes, repo-local BYO adapter plugins, watch-driven drift detection, deterministic migration/plugin failure reason codes, and conflict resolutionlive editor + preview + overlay(canvas.tab.open,canvas.overlay.mount,canvas.preview.render,canvas.preview.refresh) for browser-backed iteration; extension mode usesextension/canvas.htmlas the same-origin infinite-canvas host with pages, layers, properties, token collection or mode authoring, alias or binding controls, keyboard shortcuts, and extension-stage region annotation, while preview targets preferbound_app_runtimereconciliation for opted-in bindings and fall back to core-generatedcanvas_htmlprojections when runtime bridge preflight fails or no bound sync root existsfeedback(canvas.feedback.poll,canvas.feedback.subscribe,canvas.feedback.next,canvas.feedback.unsubscribe) for render, validation, export, editor-patch, and target-filtered feedback signals;canvas.feedback.pollremains the snapshot query, synthesizes preflight blockers while a plan is missing or invalid, and CLI and tool consumers now share the same public pull-stream contract throughsubscribe -> next -> unsubscribefigma import(canvas.document.import) resolves auth from config orFIGMA_ACCESS_TOKEN, calls the official Figma REST file, node, image, and optionalvariables/localendpoints, caches image/SVG receipts under.opendevbrowser/canvas/assets/figma/<fileKey>/, recordsdocument.meta.imports[]provenance, and keeps imports framework-neutral unless a matching framework adapter explicitly materializes the result- The canonical validator for the shipped canvas surface is
scripts/canvas-competitive-validation.mjs; it groups send-to-agent, feedback/history, adapter conformance, framework/library fixtures, plugin packaging negatives, inventory/starters, token round-trip, surface parity, Figma fixture import, configured plugin fixture status, and optional live Figma smoke into one report plus per-group logs. - Legal/compliance gating for scrape-first adapters is enforced with per-provider review checklists (review date, allowed surfaces, prohibited flows, reviewer, expiry, signed-off status) and blocks expired/invalid enablement.
- Session coherence includes cookie import validation and tiered fingerprint controls:
- Managed and
cdpConnectsessions automatically attempt to import readable cookies from the discovered system Chrome-family profile before first navigation; extension sessions reuse the already logged-in browser tab instead. - Provider cookie policy defaults are configurable via
providers.cookiePolicy(off|auto|required) andproviders.cookieSource(file|env|inline). - Workflow wrappers expose per-run overrides:
useCookiesandcookiePolicyOverride. - Effective policy is deterministic: override >
useCookies> config default. requiredpolicy can fail fast withreasonCode=auth_requiredwhen cookie load/import/verification cannot establish authenticated state.- Workflow metrics include cookie diagnostics at
meta.metrics.cookie_diagnosticsandmeta.metrics.cookieDiagnostics. - Tier 1: coherence checks/warnings (default on)
- Tier 2: runtime hardening + rotation policy (default on, continuous signals)
- Tier 3: adaptive canary/fallback track (default on, continuous signals)
- Structured JSON logging/audit provides request correlation (
requestId) and redaction-safe audit entries for write paths.
Configuration and state
- Plugin config:
~/.config/opencode/opendevbrowser.jsonc(optional). - Daemon metadata:
~/.cache/opendevbrowser/daemon.json(port, token, pid). - Daemon status:
/statusis the source of truth; cached metadata may be stale. - Daemon config:
daemonPort/daemonTokenpersisted inopendevbrowser.jsoncfor hub discovery. - Extension storage:
chrome.storage.local(relay port, token, auto-connect). - Frontend generated content (private repo):
opendevbrowser-website-deploy/frontend/src/content/*(generated docs/metrics/roadmap JSON).
Default extension values:
relayPort:8787autoConnect:trueautoPair:truepairingEnabled:truepairingToken:null(fetched via/pair)- Background auto-retry/backoff uses
chrome.alarmsfor extension auto-connect retries (/config+/pair) when the relay is unreachable.
Security controls
- Local-only CDP by default; non-local requires opt-in config.
- Relay binding:
127.0.0.1only, with token-based pairing. - Ops auth:
/opsrequires?token=<relayToken>when pairing is enabled. - Canvas auth:
/canvasrequires?token=<relayToken>when pairing is enabled. - CDP auth:
/cdprequires?token=<relayToken>when pairing is enabled (legacy). - Annotation auth:
/annotationrequires?token=<relayToken>when pairing is enabled. - Origin enforcement:
/extensionrequireschrome-extension://origin;/config,/status,/pairallow extension origins and loopback no-Origin (includingOrigin: null), and reject explicit non-extension origins. - PNA/CORS: preflights include
Access-Control-Allow-Private-Network: truewhen requested. - HTTP rate limiting:
/config,/status,/pairare rate-limited per IP. - Timing-safe compare: pairing tokens checked with
crypto.timingSafeEqual. - Output redaction: DevTools output strips sensitive tokens by default.
- Sanitized export: export pipeline removes scripts, handlers, and unsafe URLs.
Extension relay routing (flat sessions)
Extension relay mode uses flat CDP sessions (Chrome 125+). The extension CDP router:
- Lists top-level tabs and child targets for discovery.
- Auto-attaches child targets recursively (workers/OOPIF) and surfaces them in
Target.getTargetsandTarget.getTargetInfo. - Routes all commands and events by DebuggerSession
sessionId(noTarget.sendMessageToTarget). - Maintains root vs child mappings in
TargetSessionMapto route eachsessionIdto the correcttabId. - Tracks a primary tab for relay handshake/diagnostics without disconnecting other tabs.
- Annotation relay uses a dedicated
/annotationwebsocket andannotationCommand/annotationResponsemessages. - Design-canvas relay uses a dedicated
/canvaswebsocket andcanvas_*envelopes for design-tab and overlay operations.
When hub mode is enabled, the hub daemon is the sole relay owner and enforces a FIFO lease queue for multi-client safety. There is no local relay fallback in hub mode.
Testing and verification
- Unit/integration tests via Vitest (
npm run test), coverage >=97%. - Extension build via
npm run extension:build. - CLI build via
npm run build. - Private website checks via
npm run lint --prefix frontend && npm run typecheck --prefix frontend && npm run build --prefix frontendinopendevbrowser-website-deploy. - CLI inventory/help parity check via
npx opendevbrowser --helpandnpx opendevbrowser help. - CLI onboarding proof lane via
node scripts/cli-onboarding-smoke.mjs(generated help -> bundled quick-start guidance -> minimal managed happy path). - Docs drift gate via
node scripts/docs-drift-check.mjs. - Zombie duplicate audit via
node scripts/audit-zombie-files.mjs. - Chrome extension compliance gate via
node scripts/chrome-store-compliance-check.mjs. - Parity gate via
tests/parity-matrix.test.ts(contract coverage for CLI/tool/runtime surface checks + mode coverage). - Provider performance gate via
tests/providers-performance-gate.test.ts(deterministic fixture SLO checks). - Strict live release gates via
node scripts/provider-direct-runs.mjs --release-gateandnode scripts/live-regression-direct.mjs --release-gate(active live release proof layer). - Release checklist in
docs/RELEASE_RUNBOOK.mdwith evidence tracking in the current version-scoped release ledger (for this cycle:docs/RELEASE_0.0.21_EVIDENCE.md). - Benchmark fixture manifest in
docs/benchmarks/provider-fixtures.md. - First-run onboarding checklist in
docs/FIRST_RUN_ONBOARDING.md.
Skill artifacts and operational gates
opendevbrowser-best-practices includes codified operational artifacts under
skills/opendevbrowser-best-practices/artifacts/:
provider-workflows.mdparity-gates.mddebug-trace-playbook.mdfingerprint-tiers.mdmacro-workflows.mdcommand-channel-reference.md
Template assets for parity and channel checks live under
skills/opendevbrowser-best-practices/assets/templates/.
opendevbrowser-design-agent adds contract-first frontend execution assets under
skills/opendevbrowser-design-agent/, including:
artifacts/design-workflows.mdartifacts/design-contract-playbook.mdartifacts/frontend-evaluation-rubric.mdartifacts/external-pattern-synthesis.mdartifacts/research-harvest-workflow.mdartifacts/design-release-gate.mdassets/templates/design-contract.v1.jsonassets/templates/canvas-generation-plan.design.v1.jsonassets/templates/reference-pattern-board.v1.jsonassets/templates/design-release-gate.v1.jsonscripts/design-workflow.shscripts/extract-canvas-plan.sh
Skill install/discovery sync covers the canonical opencode, codex, claudecode,
and ampcli ecosystems, and path discovery is documented in README.md and
docs/CLI.md.
Validation script:
./skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh
./skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh
Key directories
src/core/: shared runtime bootstrap.src/browser/:BrowserManager,OpsBrowserManager,CanvasManager, annotation/runtime bridge clients, and session lifecycle.src/browser/fingerprint/: Tier 1/2/3 fingerprint policy + adaptive controls.src/canvas/: document store, repo persistence, export pipeline, code-sync helpers, framework adapters, library adapters, adapter plugins, kit/starter catalogs, and token references.src/integrations/figma/: Figma auth, client, normalize, URL, mapper, and asset helpers for deterministic import.src/providers/: provider contracts, registry, runtime policy, and first-party adapters acrosscommunity/,shopping/,social/,web/, plus shared helpers inshared/and guardrails insafety/.src/providers/workflows.ts: research/shopping/product-video orchestrators and compliance/alert gates.src/providers/timebox.ts: strict timebox resolver and filtering primitives.src/providers/{renderer.ts,artifacts.ts,enrichment.ts}: render modes, artifact lifecycle, and enrichment scores.src/macros/: macro parser/registry and pack definitions.src/devtools/: console/network/exception trackers and debug bundle channels.src/tools/: tool definitions and response shaping.src/relay/: relay server and protocol types.src/cli/: CLI commands, daemon/autostart,DaemonClient,RemoteManager,RemoteCanvasManager, relay status cache, and installers.src/cli/commands/artifacts.ts: artifact lifecycle cleanup (artifacts cleanup --expired-only).extension/: Chrome extension UI and background logic.opendevbrowser-website-deploy/frontend/: private website app and generated content pipeline.docs/: plans, architecture, and operational guidance.
npx opendevbrowser status