From 14bf8261da4d7e356e27d91807a34346b8e99368 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Tue, 25 Aug 2026 11:15:07 +0300 Subject: [PATCH] Authorize bounded site browser observation --- ...istant-presence-attention-human-surface.md | 2 +- ...5-human-response-continuation-semantics.md | 2 +- ...R-0019-bounded-site-browser-observation.md | 34 ++++++++++++++ dev/ACTIVE_TASK.json | 4 +- .../DEV-000293-site-browser-capability.json | 44 +++++++++++++++++++ 5 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 architecture/adrs/ADR-0019-bounded-site-browser-observation.md create mode 100644 dev/tasks/DEV-000293-site-browser-capability.json diff --git a/architecture/adrs/ADR-0014-assistant-presence-attention-human-surface.md b/architecture/adrs/ADR-0014-assistant-presence-attention-human-surface.md index 5292c9a..8e46da9 100644 --- a/architecture/adrs/ADR-0014-assistant-presence-attention-human-surface.md +++ b/architecture/adrs/ADR-0014-assistant-presence-attention-human-surface.md @@ -32,7 +32,7 @@ The system already has the correct outbound mutation foundation: Commit owns aut ## Non-goals -- No Gmail, MCP, Codex Bridge, browser automation, mobile app, voice, or self-extension loop. +- No Gmail, MCP, Codex Bridge, mobile app, voice, or self-extension loop. Browser automation is allowed only under ADR-0019 as bounded read-only observation; it is not a human-surface command or mutation channel. - No new canonical owner. - No generic scheduler/event-bus/autonomous-agent loop. - No new third-party dependency. diff --git a/architecture/adrs/ADR-0015-human-response-continuation-semantics.md b/architecture/adrs/ADR-0015-human-response-continuation-semantics.md index 494389a..7a5ffc0 100644 --- a/architecture/adrs/ADR-0015-human-response-continuation-semantics.md +++ b/architecture/adrs/ADR-0015-human-response-continuation-semantics.md @@ -30,7 +30,7 @@ Examples include: a reminder after notification, waiting work requiring a decisi ## Non-goals -- No Codex Bridge, Gmail, MCP, voice, mobile, browser automation, self-extension loop, or generalized orchestration. +- No Codex Bridge, Gmail, MCP, voice, mobile, self-extension loop, or generalized orchestration. Browser observation may be used only through the bounded read-only capability defined by ADR-0019 and cannot continue or mutate a response target. - No universal object ontology. - No reminder-specific parallel subsystem. diff --git a/architecture/adrs/ADR-0019-bounded-site-browser-observation.md b/architecture/adrs/ADR-0019-bounded-site-browser-observation.md new file mode 100644 index 0000000..820ad3c --- /dev/null +++ b/architecture/adrs/ADR-0019-bounded-site-browser-observation.md @@ -0,0 +1,34 @@ +# ADR-0019 — Bounded Site-Browser Observation + +Status: Accepted + +Task: DEV-000293 + +## Context + +Search snippets are insufficient for dynamic pages such as marketplaces: they may expose a category page while hiding the current product price behind client-side rendering. Domovoy needs a replaceable observation capability that can inspect an allowlisted rendered page without becoming an account agent, universal scraper, or external mutation path. + +## Decision + +1. Browser automation is allowed only as a server-owned, read-only observation capability behind the existing Capability and research adapter boundaries. +2. The browser runtime may navigate only to an explicit HTTPS host allowlist and bounded navigation policy. Browser-supplied or model-supplied authority, credentials, proxy settings, cookies, headers, download paths, or arbitrary JavaScript are rejected. +3. The capability may load public pages and wait for bounded client-side rendering. It may read visible text and explicitly declared structured-data selectors, then return an Epistemics Observation with source URL, observed time, coverage, and failure state. +4. Login, cookies, account state, CAPTCHA solving, checkout, form submission, uploads, downloads, purchases, messages, mutations, and external side effects are out of scope. +5. A blocked page, challenge, timeout, partial DOM, missing price, or conflicting value remains `UNKNOWN`, `PARTIAL`, or `NOT_OBSERVED`; it never becomes a verified fact by model interpretation alone. +6. Browser observation is optional. Search-only routing remains the fallback when the capability is unavailable, degraded, or not allowlisted for the requested host. +7. Capability owns availability, host policy, health and limits. Epistemics owns the resulting observation and provenance. No new canonical owner or database schema is introduced. +8. The first implementation may be development-only. Production activation requires independent capability health, allowlist evidence, adversarial navigation tests, and a live read-only smoke test. + +## Boundaries + +- Core/domain code does not import a browser or provider runtime. +- The browser adapter performs only bounded GET/navigation observation and cannot reach Commit/Executor. +- Secrets remain outside the browser runtime and its artifacts, logs, screenshots, page content and chat context. +- An observation is evidence for answer synthesis, not an instruction to mutate a site or canonical state. + +## Consequences + +- Dynamic public pages can provide stronger evidence than search snippets when the site permits it. +- Site-specific selectors and host policy are replaceable adapter configuration, not semantic domain logic. +- Browser unavailability is a capability gap, not a runtime-wide outage. +- The old blanket prohibition on browser automation is replaced by this narrower, testable boundary. diff --git a/dev/ACTIVE_TASK.json b/dev/ACTIVE_TASK.json index 986880e..e8d6130 100644 --- a/dev/ACTIVE_TASK.json +++ b/dev/ACTIVE_TASK.json @@ -1,5 +1,5 @@ { - "task_file": "dev/tasks/DEV-000292-development-mode-runtime-access.json", - "task_id": "DEV-000292", + "task_file": "dev/tasks/DEV-000293-site-browser-capability.json", + "task_id": "DEV-000293", "task_revision": 1 } diff --git a/dev/tasks/DEV-000293-site-browser-capability.json b/dev/tasks/DEV-000293-site-browser-capability.json new file mode 100644 index 0000000..cb0c259 --- /dev/null +++ b/dev/tasks/DEV-000293-site-browser-capability.json @@ -0,0 +1,44 @@ +{ + "task_id": "DEV-000293", + "task_revision": 1, + "architecture_revision": "ADR-0019", + "base_repo_revision": "origin/main", + "risk_tier": "E", + "intent": "Authorize a bounded read-only site-browser capability for dynamic web pages so Domovoy can observe rendered product data, including prices, without granting account access or external mutation authority.", + "requirement_ids": ["bounded browser observation", "dynamic web research", "price evidence extraction"], + "allowed_change_scope": { + "modules": ["capability", "epistemics", "core-runtime", "research"], + "paths": [ + "architecture/adrs/ADR-0014-assistant-presence-attention-human-surface.md", + "architecture/adrs/ADR-0015-human-response-continuation-semantics.md", + "architecture/adrs/ADR-0019-bounded-site-browser-observation.md", + "dev/ACTIVE_TASK.json", + "dev/tasks/DEV-000293-site-browser-capability.json", + "docs/PROJECT_STATUS.md" + ] + }, + "forbidden_change_scope": { + "paths": ["security/**", "database/**", "deploy/docker-compose.prod.yml", "LLM-local/**"] + }, + "allowed_architecture_delta": { + "new_cross_module_dependencies": 0, + "new_canonical_owners": 0, + "new_privileges": 0, + "new_third_party_dependencies": 0, + "new_database_owner_roles": 0 + }, + "contracts": { + "consume": ["existing capability registry", "existing epistemics observation/provenance", "existing research adapter boundary"], + "may_change": ["architecture allowance for bounded read-only browser observation"] + }, + "semantic_owner": "capability owns availability and limits; epistemics owns observations and provenance", + "canonical_state": ["no new canonical state; browser output remains an observation/artifact projection"], + "state_transitions": ["search-only observation -> bounded rendered-page observation -> source-backed answer"], + "side_effects_and_privileges": ["read-only HTTPS/browser egress only", "no cookies, account sessions, credentials, downloads, uploads, form submission or external mutation"], + "persistence_and_migrations": ["no database migration"], + "failure_retry_restart": ["timeouts and blocked pages remain partial/unknown observations", "no blind retries that can duplicate external effects"], + "assumptions": ["browser runtime is replaceable and isolated from canonical runtimes", "site allowlist and navigation policy are server-owned"], + "acceptance_scenarios": ["dynamic price page can be observed when allowlisted", "401/challenge/timeout is reported as unavailable evidence", "browser cannot submit credentials or mutate a site", "source URL, observed time and coverage remain attached", "existing search-only route remains unchanged when browser capability is unavailable", "production behavior stays read-only"], + "required_tests": ["architecture preflight", "check-diff", "ADR consistency", "go test ./...", "go vet ./...", "go run ./cmd/devctl check-architecture", "go run ./cmd/devctl independent", "git diff --check"], + "terminal_gap_states": ["BLOCKED_BY_ARCHITECTURE_GAP", "BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_CONFLICT", "BLOCKED_BY_MISSING_CAPABILITY"] +} -- 2.54.0