Skip to content

v1.1.1: SOCA bridge hardening, provider partitioning, lean composer#19

Open
arnaudassoumani-collab wants to merge 5 commits intoOpenBrowserAI:mainfrom
arnaudassoumani-collab:codex/openbrowser-v1.1.1-soca-bridge-hardening
Open

v1.1.1: SOCA bridge hardening, provider partitioning, lean composer#19
arnaudassoumani-collab wants to merge 5 commits intoOpenBrowserAI:mainfrom
arnaudassoumani-collab:codex/openbrowser-v1.1.1-soca-bridge-hardening

Conversation

@arnaudassoumani-collab
Copy link

@arnaudassoumani-collab arnaudassoumani-collab commented Feb 26, 2026

Summary

Ship OpenBrowser v1.1.1 hardening for deterministic provider routing, Tailscale bridge reliability, model-origin partitioning, lean chat composer UX, and release evidence gating.

Linked Issues

What Changed

  • Added shared endpoint policy module (chromium-extension/src/llm/endpointPolicy.ts) and refactored options/background/llm callers.
  • Corrected provider routing split:
    • Bridge routed: soca-bridge, vps-holo
    • Direct cloud: openai, anthropic, google, openrouter, azure, bedrock, opencode-zen
  • Enforced model-origin and catalog partitioning via catalogMode + modelOrigin.
  • Restored direct OpenRouter behavior (no bridge reroute).
  • Strengthened bridge checks with candidate probing + actionable statuses.
  • Simplified chat composer into lean default + explicit advanced drawer (ComposerCore, ComposerAdvanced, QuickActionsMenu, SocaKitPanel).
  • Bumped versions to 1.1.1 and generated immutable pack chromium-extension-versions/v1.1.1.
  • Updated version catalog and release notes.
  • Added deterministic SOCA gate script and generated evidence bundle.

SOCA Gate

  • Report: reports/v1.1.1/soca-gate.md
  • JSON: reports/v1.1.1/soca-gate.json
  • Metrics:
    • RSI: 100
    • ZHV: 100
    • ZHDEEV: 100
    • TRUST SCORE: 100

Evidence Bundle Paths

  • reports/v1.1.1/provider-matrix.log
  • reports/v1.1.1/no-egress.log
  • reports/v1.1.1/bridge-probes.log
  • reports/v1.1.1/release-diff.txt
  • reports/v1.1.1/pack-hashes.txt
  • reports/v1.1.1/screenshots/settings-provider-models.png

Validation

  • pnpm -C chromium-extension check:drift
  • pnpm -C chromium-extension build
  • pnpm -C chromium-extension test:e2e --grep "Provider model refresh matrix covers bridge/api-key/oauth modes"
  • pnpm -C chromium-extension test:e2e --grep "SW cannot fetch public internet"
  • scripts/release/soca_gate_v1_1_1.sh

PR Checklist

  • All tests green
  • Gate report attached
  • Evidence bundle paths listed
  • Rollback steps documented

Rollback

  1. Reload immutable pack v1.1.0 from chromium-extension-versions/CATALOG.json.
  2. Revert only v1.1.1 commits from this PR branch.
  3. Re-run scripts/release/soca_gate_v1_1_1.sh to verify restored posture.

arnaud assoumani and others added 5 commits January 27, 2026 12:34
- Add 5 YAML workflow templates (preflight, vps-capsule, clawdbot-deploy, openbrowser-setup, evidence-bundle)
- Add 5 vault templates for SOCA_HOLOBIONT_OS Obsidian vault
- Add 3 agent prompts (workflow-executor, openbrowser-observer, vps-operator)
- Add workflow documentation README

Part of Constitution Rule 66: OpenBrowser Automation Workflows
Copilot AI review requested due to automatic review settings February 26, 2026 22:59
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Delivers OpenBrowser v1.1.1 hardening across the SOCA bridge and extension ecosystem, including deterministic provider routing, offline/online lane constraints, evidence bundling, and an app-builder action runner.

Changes:

  • Added PromptBuddy “local deterministic” enhancement service + routes, static offline import gate, and evidence bundle writer.
  • Extended SOCA bridge capabilities: model catalog merging, alias model resolution, allowlisted online fetch endpoints, and evidence capture.
  • Added immutable Chromium extension version packs + catalog, plus an app-builder Action DSL runner and builder action templates.

Reviewed changes

Copilot reviewed 35 out of 931 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
chromium-extension-versions/v1.0.7/PACK_INFO.md Adds pack metadata for v1.0.7.
chromium-extension-versions/v1.0.6/sidebar.html Adds immutable v1.0.6 sidebar entrypoint HTML.
chromium-extension-versions/v1.0.6/options.html Adds immutable v1.0.6 options entrypoint HTML.
chromium-extension-versions/v1.0.6/manifest.json Adds immutable v1.0.6 extension manifest snapshot.
chromium-extension-versions/v1.0.6/js/content_script.js Adds immutable v1.0.6 built content script stub.
chromium-extension-versions/v1.0.6/PACK_INFO.md Adds pack metadata for v1.0.6.
chromium-extension-versions/v1.0.5/sidebar.html Adds immutable v1.0.5 sidebar entrypoint HTML.
chromium-extension-versions/v1.0.5/options.html Adds immutable v1.0.5 options entrypoint HTML.
chromium-extension-versions/v1.0.5/manifest.json Adds immutable v1.0.5 extension manifest snapshot.
chromium-extension-versions/v1.0.5/js/content_script.js Adds immutable v1.0.5 built content script stub.
chromium-extension-versions/v1.0.5/PACK_INFO.md Adds pack metadata for v1.0.5.
chromium-extension-versions/v1.0.4/sidebar.html Adds immutable v1.0.4 sidebar entrypoint HTML.
chromium-extension-versions/v1.0.4/options.html Adds immutable v1.0.4 options entrypoint HTML.
chromium-extension-versions/v1.0.4/manifest.json Adds immutable v1.0.4 extension manifest snapshot.
chromium-extension-versions/v1.0.4/js/content_script.js Adds immutable v1.0.4 built content script stub.
chromium-extension-versions/v1.0.4/PACK_INFO.md Adds pack metadata for v1.0.4.
chromium-extension-versions/README.md Documents immutable version pack usage and creation flow.
chromium-extension-versions/CATALOG.json Adds version catalog listing available packs through v1.1.1.
bridge/version.py Introduces SSOT bridge/schema version constants.
bridge/promptbuddy_static_gate.py Adds static scan to forbid network-capable imports in PromptBuddy offline components.
bridge/promptbuddy_service.py Adds deterministic local prompt enhancement + redaction + diff generation.
bridge/promptbuddy_routes.py Adds PromptBuddy API routes (health/capabilities/profiles/selftest/enhance) + evidence writing.
bridge/promptbuddy_models.py Adds Pydantic request/response schema for PromptBuddy endpoints.
bridge/promptbuddy_evidence.py Adds PromptBuddy evidence bundle writer with sha256 manifest.
bridge/openapi_snapshot.json Adds an OpenAPI snapshot with PromptBuddy surfaces included.
bridge/app.py Expands bridge app with policy checks, model catalog routing, online allowlist gating, and evidence capture.
bridge/PROMPTBUDDY.md Adds PromptBuddy bridge documentation and asset locations.
app_builder/run_action_spec.ts Adds Playwright-based Action DSL runner with HIL pauses and evidence gating.
app_builder/actions/lovable.actions.v1.json Adds Lovable action spec template.
app_builder/actions/google_ai_studio_build.actions.v1.json Adds Google AI Studio Build action spec template.
app_builder/actions/antigravity.actions.v1.json Adds Antigravity action spec template.
app_builder/SOCA_APP_BUILDER_BLUEPRINT.v1.json Adds builder blueprint describing policies, inputs, builders, and evidence requirements.
app_builder/README.md Documents app-builder purpose, files, and extension points.
RELEASES.md Adds release notes for v1.1.1 and prior versions.
README.md Links to official operations guides and PromptBuddy notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

SSOT version constants for the SOCA OpenBrowser Bridge.
"""

BRIDGE_VERSION = "v1.1.0"
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BRIDGE_VERSION is set to v1.1.0, but this PR is explicitly shipping v1.1.1. This will cause inconsistent reporting (health/capabilities User-Agent strings, evidence metadata, etc.). Update the constant to v1.1.1 (and ensure any other “version” surfaces are consistent with this SSOT).

Suggested change
BRIDGE_VERSION = "v1.1.0"
BRIDGE_VERSION = "v1.1.1"

Copilot uses AI. Check for mistakes.
},
"info": {
"title": "SOCA OpenBrowser Bridge",
"version": "v1.0.0"
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OpenAPI snapshot reports info.version as v1.0.0, which conflicts with the bridge’s SSOT version constants and the v1.1.1 release context. Regenerate or update this snapshot so info.version matches the shipped bridge version, otherwise clients/users will see misleading API versioning.

Suggested change
"version": "v1.0.0"
"version": "v1.1.1"

Copilot uses AI. Check for mistakes.
Comment on lines +111 to +113
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "soca").strip()
if not expected:
return
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting the bearer token to a well-known value ("soca") makes authorization effectively guessable in any non-local deployment. Prefer requiring an explicitly configured token (e.g., default to empty and treat empty as “no auth” only when bound to localhost), or generate a per-install secret and explicitly log/configure it.

Suggested change
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "soca").strip()
if not expected:
return
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "").strip()
if not expected:
# Fail closed if the bridge token is not configured, to avoid using a
# guessable default or accidentally running without authentication.
raise HTTPException(
status_code=500,
detail="SOCA_OPENBROWSER_BRIDGE_TOKEN is not configured",
)

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +116
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "soca").strip()
if not expected:
return
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as in promptbuddy_routes.py: the default bearer token is a predictable shared secret. This is particularly risky here because the server defaults to binding 0.0.0.0 (reachable over Tailscale/VPS) and exposes higher-impact endpoints. Make the token explicitly configured (or at least fail startup when binding non-local and the token is unset/weak).

Suggested change
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "soca").strip()
if not expected:
return
expected = os.environ.get("SOCA_OPENBROWSER_BRIDGE_TOKEN", "").strip()
# Require an explicitly configured, non-trivial token to avoid insecure defaults.
# If the token is unset or obviously weak, treat this as a server misconfiguration.
if not expected or len(expected) < 16:
raise HTTPException(
status_code=500,
detail="server misconfigured: SOCA_OPENBROWSER_BRIDGE_TOKEN must be set "
"to a sufficiently long, random value",
)

Copilot uses AI. Check for mistakes.
Comment on lines +280 to +281
original_prompt=req.prompt,
enhanced_prompt=enhanced_prompt,
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evidence bundles persist the full request (req.model_dump()), which includes the raw prompt. Even in safe_exec mode (where you redact for processing), the evidence will still store the original secret-bearing text. Consider redacting before writing evidence (at least for Mode.safe_exec), or storing a minimized request payload (e.g., hashes + redaction metadata) to avoid leaking secrets into runs/.

Copilot uses AI. Check for mistakes.
Comment on lines +301 to +304
write_evidence_bundle(
enhancement_id=enhancement_id,
req=req.model_dump(),
resp=response.model_dump(exclude_none=False),
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evidence bundles persist the full request (req.model_dump()), which includes the raw prompt. Even in safe_exec mode (where you redact for processing), the evidence will still store the original secret-bearing text. Consider redacting before writing evidence (at least for Mode.safe_exec), or storing a minimized request payload (e.g., hashes + redaction metadata) to avoid leaking secrets into runs/.

Copilot uses AI. Check for mistakes.
Comment on lines +1730 to +1731
"truncated": truncated or len(excerpt) < len(text),
"text": excerpt[:20000],
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

truncated will almost always be True because excerpt is intentionally a snippet (often shorter than text) even when the upstream fetch was not truncated. This makes the field inaccurate for callers. Recommend setting truncated based on fetch truncation and explicit output limiting (e.g., whether you clipped to max_bytes / max_chars), rather than comparing excerpt length to the full fetched text.

Copilot uses AI. Check for mistakes.
}

async function ensureEmptyDir(dir: string): Promise<void> {
await fs.mkdir(dir, { recursive: true });
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensureEmptyDir does not actually empty the directory, it only ensures it exists. If --run-dir is provided and points to a non-empty directory, artifacts can be mixed across runs while the evidence gate still passes unexpectedly. Either (a) rename this to reflect behavior (e.g., ensureDir), or (b) implement “empty” semantics (delete contents or fail if non-empty).

Suggested change
await fs.mkdir(dir, { recursive: true });
try {
const stats = await fs.stat(dir);
if (!stats.isDirectory()) {
throw new Error(`not_a_directory: ${dir}`);
}
} catch (err) {
const e = err as NodeJS.ErrnoException;
if (e.code === "ENOENT") {
// Directory does not exist; create it.
await fs.mkdir(dir, { recursive: true });
return;
}
throw err;
}
const entries = await fs.readdir(dir);
if (entries.length > 0) {
throw new Error(`directory_not_empty: ${dir}`);
}

Copilot uses AI. Check for mistakes.
} else if (a === "--json") {
args.jsonStdout = true;
} else if (a === "--slowmo-ms") {
args.slowMoMs = Number(next(i));
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Number(next(i)) can produce NaN for invalid input (e.g., --slowmo-ms foo), which then propagates into chromium.launch({ slowMo: ... }) and can fail at runtime. Validate this argument (finite, >= 0) and throw a clear CLI error when invalid.

Suggested change
args.slowMoMs = Number(next(i));
const valueStr = next(i);
const value = Number(valueStr);
if (!Number.isFinite(value) || value < 0) {
throw new Error(
`invalid_value_for:--slowmo-ms (expected non-negative number, got "${valueStr}")`
);
}
args.slowMoMs = value;

Copilot uses AI. Check for mistakes.
- Generated UTC: 2026-02-24T15:55:07Z
- Source commit: bd4c1a9
- Source: `core/tools/openbrowser/chromium-extension/dist`
- Load in Chromium: `chrome://extensions` -> Developer mode -> Load unpacked -> `/Users/arnaudassoumani/SOCA/core/tools/openbrowser/chromium-extension-versions/v1.0.6`
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loading instructions include an absolute user-specific path (/Users/...). This makes the pack docs non-portable for other developers/CI checkouts. Prefer a repo-relative path (e.g., core/tools/openbrowser/chromium-extension-versions/v1.0.6) or a placeholder like <repo_root>/core/tools/....

Suggested change
- Load in Chromium: `chrome://extensions` -> Developer mode -> Load unpacked -> `/Users/arnaudassoumani/SOCA/core/tools/openbrowser/chromium-extension-versions/v1.0.6`
- Load in Chromium: `chrome://extensions` -> Developer mode -> Load unpacked -> `<repo_root>/core/tools/openbrowser/chromium-extension-versions/v1.0.6`

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants