feat(executors): add isolated Claude Code bridge over Devin ACP (#8914)

Validated in post-merge-train sweep (boards clean on release/v3.8.50 tip)
This commit is contained in:
Lucas Israel
2026-08-06 11:08:37 -03:00
committed by GitHub
parent 813dbb6e03
commit 2a94cbfe14
51 changed files with 5106 additions and 0 deletions

5
scripts/devin-bridge/build Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
bridge_prepare_sandbox
docker compose -f "$BRIDGE_COMPOSE" --profile offline build

12
scripts/devin-bridge/clean Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
if [[ "${1:-}" == "--all" ]]; then
docker compose -f "$BRIDGE_COMPOSE" --profile offline --profile live-devin down \
--remove-orphans --volumes
printf 'Containers, networks, and bridge-owned named volumes were removed.\n'
else
docker compose -f "$BRIDGE_COMPOSE" --profile offline --profile live-devin down \
--remove-orphans
printf 'Containers and networks stopped. Named auth/config volumes were preserved; use --all to remove them.\n'
fi

131
scripts/devin-bridge/common Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail
BRIDGE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
BRIDGE_COMPOSE="$BRIDGE_ROOT/docker/devin-bridge/compose.yml"
BRIDGE_SANDBOX="$BRIDGE_ROOT/.sandbox"
BRIDGE_GUARD_AUDIT_ROOT="$BRIDGE_SANDBOX/guard-audit"
BRIDGE_CLAUDE_AUDIT="$BRIDGE_GUARD_AUDIT_ROOT/claude/egress.jsonl"
BRIDGE_DEVIN_AUDIT="$BRIDGE_GUARD_AUDIT_ROOT/devin/egress.jsonl"
BRIDGE_RUNTIME_POLICY="$BRIDGE_ROOT/scripts/devin-bridge/runtime-policy.mjs"
bridge_prepare_sandbox() {
mkdir -p "$BRIDGE_SANDBOX/home" "$BRIDGE_SANDBOX/test-data" \
"$BRIDGE_SANDBOX/e2e-workspace" "$BRIDGE_SANDBOX/live-workspace" \
"$BRIDGE_SANDBOX/evidence" "$BRIDGE_GUARD_AUDIT_ROOT/claude" \
"$BRIDGE_GUARD_AUDIT_ROOT/devin"
chmod 0777 "$BRIDGE_SANDBOX/e2e-workspace" "$BRIDGE_SANDBOX/live-workspace" \
"$BRIDGE_SANDBOX/evidence"
chmod 01777 "$BRIDGE_GUARD_AUDIT_ROOT/claude" "$BRIDGE_GUARD_AUDIT_ROOT/devin"
}
bridge_reset_guard_audit() {
local audit_path="$1"
local audit_dir
local temp_path
bridge_prepare_sandbox
audit_dir="$(dirname "$audit_path")"
temp_path="$(mktemp "$audit_dir/.egress.jsonl.XXXXXX")"
chmod 0666 "$temp_path"
mv -f "$temp_path" "$audit_path"
}
bridge_reset_claude_egress_audit() {
bridge_reset_guard_audit "$BRIDGE_CLAUDE_AUDIT"
}
bridge_reset_devin_egress_audit() {
bridge_reset_guard_audit "$BRIDGE_DEVIN_AUDIT"
}
bridge_reset_e2e_fixture() {
bridge_prepare_sandbox
cp -R "$BRIDGE_ROOT/tests/fixtures/devin-bridge/e2e-workspace/." \
"$BRIDGE_SANDBOX/e2e-workspace/"
rm -f "$BRIDGE_SANDBOX/e2e-workspace/.e2e-hook.log" \
"$BRIDGE_SANDBOX/evidence/claude-stream.jsonl" \
"$BRIDGE_SANDBOX/evidence/mock-acp.jsonl"
bridge_reset_claude_egress_audit
}
bridge_reset_live_fixture() {
bridge_prepare_sandbox
cp -R "$BRIDGE_ROOT/tests/fixtures/devin-bridge/e2e-workspace/." \
"$BRIDGE_SANDBOX/live-workspace/"
rm -f "$BRIDGE_SANDBOX/live-workspace/.e2e-hook.log" \
"$BRIDGE_SANDBOX/evidence/live-analysis.jsonl" \
"$BRIDGE_SANDBOX/evidence/live-fix.jsonl" \
"$BRIDGE_SANDBOX/evidence/live-command.jsonl" \
"$BRIDGE_SANDBOX/evidence/live-models.json" \
"$BRIDGE_SANDBOX/evidence/egress.jsonl"
bridge_reset_claude_egress_audit
bridge_reset_devin_egress_audit
}
bridge_test_env() {
bridge_prepare_sandbox
env HOME="$BRIDGE_SANDBOX/home" DATA_DIR="$BRIDGE_SANDBOX/test-data" SQLITE_FILE="$BRIDGE_SANDBOX/test-data/storage.sqlite" DEVIN_AGENTIC_HOME="$BRIDGE_SANDBOX/home" "$@"
}
bridge_run_devin() {
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin run --rm --no-deps \
omniroute-live sh -ceu '
trusted_proxy=http://network-guard:8080
test "${DEVIN_BRIDGE_PROXY_URL:-}" = "$trusted_proxy"
export HTTP_PROXY="$trusted_proxy" HTTPS_PROXY="$trusted_proxy"
unset ALL_PROXY NO_PROXY http_proxy https_proxy all_proxy no_proxy
exec devin "$@"
' bridge-devin "$@"
}
bridge_assert_devin_auth_status() {
local exit_status="$1"
local output="$2"
printf '%s' "$output" | node --input-type=module -e '
import { pathToFileURL } from "node:url";
import fs from "node:fs";
const policy = await import(pathToFileURL(process.argv[1]));
const result = policy.validateDevinAuthStatus(process.argv[2], fs.readFileSync(0, "utf8"));
if (!result.ok) throw new Error(result.error);
' "$BRIDGE_RUNTIME_POLICY" "$exit_status"
}
bridge_check_devin_auth() {
local output
local exit_status
set +e
output="$(bridge_run_devin auth status 2>&1)"
exit_status=$?
set -e
bridge_assert_devin_auth_status "$exit_status" "$output"
printf 'PASS: Devin authentication confirmed\n'
}
bridge_assert_zero_claude_egress() {
local audit_path="$1"
bridge_validate_guard_audit claude-zero "$audit_path"
}
bridge_assert_claude_guard_denials() {
local audit_path="$1"
bridge_validate_guard_audit claude-denials "$audit_path"
}
bridge_assert_devin_guard_audit() {
local audit_path="$1"
bridge_validate_guard_audit devin-allowed "$audit_path"
}
bridge_validate_guard_audit() {
local kind="$1"
local audit_path="$2"
node --input-type=module -e '
import { pathToFileURL } from "node:url";
const policy = await import(pathToFileURL(process.argv[1]));
policy.validateAuditFile(process.argv[2], process.argv[3], process.argv[4]);
' "$BRIDGE_RUNTIME_POLICY" "$kind" "$audit_path" "$(id -u)"
}
bridge_export_guard_audit() {
local audit_path="$1"
local evidence_name="$2"
cp "$audit_path" "$BRIDGE_SANDBOX/evidence/$evidence_name"
chmod 0644 "$BRIDGE_SANDBOX/evidence/$evidence_name"
}
bridge_cleanup_compose() {
docker compose -f "$BRIDGE_COMPOSE" --profile offline --profile live-devin \
down --remove-orphans >/dev/null 2>&1 || true
}

28
scripts/devin-bridge/launch Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
trap bridge_cleanup_compose EXIT
bridge_cleanup_compose
bridge_prepare_sandbox
"$(dirname "$0")/verify-anthropic-isolation"
bridge_reset_claude_egress_audit
bridge_reset_devin_egress_audit
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin up -d --wait network-guard claude-egress-guard
bridge_check_devin_auth
bridge_run_devin models list --format json >"$BRIDGE_SANDBOX/evidence/live-models.json"
devin_model="$(node --import tsx/esm "$BRIDGE_ROOT/scripts/devin-bridge/select-live-model.mjs" \
<"$BRIDGE_SANDBOX/evidence/live-models.json")"
export DEVIN_BRIDGE_MODEL="devin-cli-agentic/$devin_model"
export DEVIN_BRIDGE_SONNET_MODEL="${DEVIN_BRIDGE_SONNET_MODEL:-$DEVIN_BRIDGE_MODEL}"
export DEVIN_BRIDGE_OPUS_MODEL="${DEVIN_BRIDGE_OPUS_MODEL:-$DEVIN_BRIDGE_MODEL}"
export DEVIN_BRIDGE_HAIKU_MODEL="${DEVIN_BRIDGE_HAIKU_MODEL:-$DEVIN_BRIDGE_MODEL}"
export DEVIN_BRIDGE_SUBAGENT_MODEL="${DEVIN_BRIDGE_SUBAGENT_MODEL:-$DEVIN_BRIDGE_MODEL}"
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin up -d --wait omniroute-live
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin run --rm --no-deps \
claude-live claude
bridge_cleanup_compose
bridge_assert_devin_guard_audit "$BRIDGE_DEVIN_AUDIT"
bridge_assert_zero_claude_egress "$BRIDGE_CLAUDE_AUDIT"
bridge_export_guard_audit "$BRIDGE_DEVIN_AUDIT" egress.jsonl
bridge_export_guard_audit "$BRIDGE_CLAUDE_AUDIT" claude-egress.jsonl
trap - EXIT

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
[[ "${ENABLE_LIVE_DEVIN_TESTS:-}" == 1 ]] || { echo 'Set ENABLE_LIVE_DEVIN_TESTS=1' >&2; exit 1; }
trap bridge_cleanup_compose EXIT
bridge_cleanup_compose
bridge_prepare_sandbox
bridge_reset_devin_egress_audit
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin up -d --wait network-guard
bridge_run_devin auth login --force-manual-token-flow
bridge_cleanup_compose
trap - EXIT
exec env ENABLE_LIVE_DEVIN_TESTS=1 "$(dirname "$0")/test-live-devin"

View File

@@ -0,0 +1,111 @@
import fs from "node:fs";
const ALLOWED_DEVIN_SUFFIXES = [".devin.ai", ".cognition.ai"];
const ALLOWED_DEVIN_EXACT = ["server.codeium.com", "unleash.codeium.com"];
function normalizedHostname(value) {
return String(value || "")
.trim()
.toLowerCase()
.replace(/\.$/, "");
}
export function isAllowedDevinAuditHostname(hostname) {
const value = normalizedHostname(hostname);
return (
ALLOWED_DEVIN_EXACT.includes(value) ||
ALLOWED_DEVIN_SUFFIXES.some((suffix) => value === suffix.slice(1) || value.endsWith(suffix))
);
}
export function validateDevinAuthStatus(exitStatus, output) {
if (Number(exitStatus) !== 0) return { ok: false, error: "auth status command failed" };
const lines = String(output)
.split(/\r?\n/)
.map((line) => line.trim());
if (!lines.some((line) => /^Logged in \(via Devin\)\.?$/.test(line))) {
return { ok: false, error: "auth status did not confirm login" };
}
if (lines.some((line) => /failed to fetch from server/i.test(line))) {
return { ok: false, error: "auth status could not confirm server access" };
}
return { ok: true };
}
export function parseAuditEntries(text) {
const lines = String(text)
.split(/\r?\n/)
.filter((line) => line.trim().length > 0);
return lines.map((line) => JSON.parse(line));
}
export function validateZeroClaudeEgress(text) {
if (String(text).length !== 0) {
return { ok: false, error: "Claude attempted external egress during the real run" };
}
return { ok: true };
}
export function validateClaudeGuardDenials(text) {
const entries = parseAuditEntries(text);
if (!entries.length) return { ok: false, error: "Claude egress audit has no records" };
if (entries.some((entry) => entry.decision !== "deny")) {
return { ok: false, error: "Claude egress audit contains a non-deny decision" };
}
for (const hostname of ["api.anthropic.com", "claude.ai"]) {
if (!entries.some((entry) => entry.hostname === hostname && entry.decision === "deny")) {
return { ok: false, error: `Claude egress audit is missing deny for ${hostname}` };
}
}
return { ok: true };
}
export function validateDevinGuardAudit(text) {
const entries = parseAuditEntries(text);
if (!entries.length) return { ok: false, error: "Devin egress audit has no records" };
let sawAllowedDevinRequest = false;
for (const entry of entries) {
if (entry.decision === "deny") {
if (/anthropic|claude\.ai/i.test(normalizedHostname(entry.hostname))) {
return { ok: false, error: `forbidden Devin egress attempt: ${String(entry.hostname)}` };
}
continue;
}
if (entry.decision !== "allow" || !isAllowedDevinAuditHostname(entry.hostname)) {
return { ok: false, error: `unexpected Devin egress record: ${String(entry.hostname)}` };
}
sawAllowedDevinRequest = true;
}
return sawAllowedDevinRequest
? { ok: true }
: { ok: false, error: "Devin egress audit has no approved request" };
}
export function validateAuditFileStat(stat, expectedUid) {
if (!stat || !stat.isFile() || stat.isSymbolicLink()) return "audit path is not a regular file";
if (stat.nlink !== 1) return "audit file link count is not one";
if (stat.uid !== Number(expectedUid)) return "audit file owner mismatch";
if ((stat.mode & 0o777) !== 0o666) return "audit file mode mismatch";
return null;
}
export function readValidatedAuditFile(path, expectedUid) {
const stat = fs.lstatSync(path);
const statError = validateAuditFileStat(stat, expectedUid);
if (statError) throw new Error(statError);
return fs.readFileSync(path, "utf8");
}
export function validateAuditFile(kind, path, expectedUid) {
const text = readValidatedAuditFile(path, expectedUid);
const result =
kind === "claude-zero"
? validateZeroClaudeEgress(text)
: kind === "claude-denials"
? validateClaudeGuardDenials(text)
: kind === "devin-allowed"
? validateDevinGuardAudit(text)
: { ok: false, error: `unknown audit validation kind: ${kind}` };
if (!result.ok) throw new Error(result.error);
return text;
}

View File

@@ -0,0 +1,101 @@
#!/usr/bin/env node
import fs from "node:fs";
import { pathToFileURL } from "node:url";
import { DEVIN_MODEL_CATALOG } from "../../open-sse/config/providers/registry/devin/catalog.ts";
const candidateFields = new Set([
"model_id",
"modelId",
"model_uid",
"modelUid",
"family_uid",
"familyUid",
]);
function normalizeModelId(value) {
return value
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
function collect(value, candidates) {
if (Array.isArray(value)) {
value.forEach((item) => collect(item, candidates));
return;
}
if (!value || typeof value !== "object") return;
for (const [key, nested] of Object.entries(value)) {
if (
typeof nested === "string" &&
candidateFields.has(key) &&
/^[a-z0-9][a-z0-9._/-]*$/i.test(nested)
) {
candidates.push(nested);
}
collect(nested, candidates);
}
}
export function selectLiveModel(
document,
environment = process.env,
catalog = DEVIN_MODEL_CATALOG
) {
const candidates = [];
collect(document, candidates);
const unique = [...new Set(candidates)];
const normalizedCatalog = new Map();
for (const entry of catalog) {
const normalized = normalizeModelId(entry.id);
const existing = normalizedCatalog.get(normalized) || [];
existing.push(entry.id);
normalizedCatalog.set(normalized, existing);
}
for (const [normalized, ids] of normalizedCatalog) {
if (ids.length > 1) {
throw new Error(
`Ambiguous OmniRoute catalog normalization for ${normalized}: ${ids.join(", ")}`
);
}
}
const catalogIds = new Set(catalog.map((entry) => entry.id));
const available = [
...new Set(
unique
.map((candidate) => normalizeModelId(candidate))
.filter((candidate) => normalizedCatalog.has(candidate))
),
];
for (const [name, configured] of [
["DEVIN_BRIDGE_SONNET_MODEL", environment.DEVIN_BRIDGE_SONNET_MODEL],
["DEVIN_BRIDGE_OPUS_MODEL", environment.DEVIN_BRIDGE_OPUS_MODEL],
["DEVIN_BRIDGE_HAIKU_MODEL", environment.DEVIN_BRIDGE_HAIKU_MODEL],
["DEVIN_BRIDGE_SUBAGENT_MODEL", environment.DEVIN_BRIDGE_SUBAGENT_MODEL],
]) {
if (!configured) continue;
const prefix = "devin-cli-agentic/";
const modelId = configured.startsWith(prefix) ? configured.slice(prefix.length) : "";
if (!modelId || !catalogIds.has(modelId) || !available.includes(modelId)) {
throw new Error(`${name} is not a model returned by Devin and present in OmniRoute`);
}
}
const selected =
available.find((candidate) => candidate === "swe-1-7-lightning") ||
available.find((candidate) => candidate === "swe-1-7") ||
available.find((candidate) => /swe|claude|gpt|gemini/i.test(candidate)) ||
available[0];
if (!selected) {
throw new Error("Devin returned no model identifier present in OmniRoute's Devin catalog");
}
return selected;
}
if (process.argv[1] && pathToFileURL(process.argv[1]).href === import.meta.url) {
const document = JSON.parse(fs.readFileSync(0, "utf8"));
process.stdout.write(selectLiveModel(document));
}

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
bridge_prepare_sandbox
rm -f "$BRIDGE_SANDBOX/evidence/mock-acp.jsonl"
"$(dirname "$0")/verify-anthropic-isolation" --static
docker compose -f "$BRIDGE_COMPOSE" --profile offline down --remove-orphans
docker compose -f "$BRIDGE_COMPOSE" --profile offline up --abort-on-container-exit \
--exit-code-from contract contract
node -e '
const fs = require("node:fs");
const rows = fs.readFileSync(process.argv[1], "utf8").trim().split("\n").map(JSON.parse);
const repairRows = rows.filter((row) => row.scenario === "narrative-repair");
if (
rows.length !== 7 ||
rows.some((row) => row.provider !== "devin-cli-agentic") ||
repairRows.length !== 2 ||
repairRows[0].stage !== "initial" ||
repairRows[1].stage !== "repair"
) {
throw new Error("wire contract observed a missing or non-Devin provider");
}
' "$BRIDGE_SANDBOX/evidence/mock-acp.jsonl"
printf 'PASS: bridge wire contract suite completed without provider fallback\n'

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
trap bridge_cleanup_compose EXIT
bridge_cleanup_compose
bridge_reset_e2e_fixture
"$(dirname "$0")/verify-anthropic-isolation" --static
docker compose -f "$BRIDGE_COMPOSE" --profile offline up --abort-on-container-exit \
--exit-code-from claude claude
grep -q '"action":"final"' "$BRIDGE_SANDBOX/evidence/mock-acp.jsonl"
grep -q 'BRIDGE_E2E_COMPLETE' "$BRIDGE_SANDBOX/evidence/claude-stream.jsonl"
bridge_cleanup_compose
bridge_assert_zero_claude_egress "$BRIDGE_CLAUDE_AUDIT"
bridge_export_guard_audit "$BRIDGE_CLAUDE_AUDIT" claude-egress.jsonl
trap - EXIT
printf 'PASS: real Claude Code completed the offline agentic fixture\n'

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
[[ "${ENABLE_LIVE_DEVIN_TESTS:-}" == 1 ]] || { echo 'Set ENABLE_LIVE_DEVIN_TESTS=1' >&2; exit 1; }
trap bridge_cleanup_compose EXIT
bridge_cleanup_compose
bridge_reset_live_fixture
"$(dirname "$0")/verify-anthropic-isolation" --static
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin up -d --wait network-guard
bridge_check_devin_auth
models_file="$BRIDGE_SANDBOX/evidence/live-models.json"
if [[ -n "${DEVIN_BRIDGE_DISCOVERED_MODEL:-}" ]]; then
devin_model="$DEVIN_BRIDGE_DISCOVERED_MODEL"
else
for attempt in 1 2 3; do
if bridge_run_devin models list --format json >"$models_file"; then
break
fi
[[ "$attempt" == 3 ]] && exit 1
sleep 1
done
devin_model="$(node --import tsx/esm "$BRIDGE_ROOT/scripts/devin-bridge/select-live-model.mjs" \
<"$models_file")"
fi
export DEVIN_BRIDGE_MODEL="devin-cli-agentic/$devin_model"
export DEVIN_BRIDGE_SONNET_MODEL="$DEVIN_BRIDGE_MODEL"
export DEVIN_BRIDGE_OPUS_MODEL="$DEVIN_BRIDGE_MODEL"
export DEVIN_BRIDGE_HAIKU_MODEL="$DEVIN_BRIDGE_MODEL"
export DEVIN_BRIDGE_SUBAGENT_MODEL="$DEVIN_BRIDGE_MODEL"
docker compose -f "$BRIDGE_COMPOSE" --profile live-devin up --abort-on-container-exit --exit-code-from claude-live claude-live
bridge_cleanup_compose
bridge_assert_devin_guard_audit "$BRIDGE_DEVIN_AUDIT"
bridge_assert_zero_claude_egress "$BRIDGE_CLAUDE_AUDIT"
bridge_export_guard_audit "$BRIDGE_DEVIN_AUDIT" egress.jsonl
bridge_export_guard_audit "$BRIDGE_CLAUDE_AUDIT" claude-egress.jsonl
trap - EXIT
printf 'PASS: live model %s was discovered and validated by three scenarios\n' "$devin_model"

9
scripts/devin-bridge/test-unit Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
cd "$BRIDGE_ROOT"
bridge_test_env node --import tsx/esm --test \
tests/unit/executor-devin-cli-agentic-core.test.ts \
tests/unit/executor-devin-cli-agentic-acp.test.ts \
tests/unit/devin-bridge-network-guard.test.ts \
tests/unit/devin-bridge-live-runtime.test.ts

View File

@@ -0,0 +1,125 @@
#!/usr/bin/env node
import fs from "node:fs";
import { pathToFileURL } from "node:url";
function contentBlocks(message) {
return Array.isArray(message?.message?.content) ? message.message.content : [];
}
export function validateClaudeEvidenceText(text, options) {
const marker = String(options?.marker || "").trim();
const requiredTools = Array.isArray(options?.requiredTools) ? options.requiredTools : [];
if (!marker) throw new Error("A final marker is required");
const toolUses = new Map();
const successfulResults = new Set();
const slashCommands = new Set();
const skills = new Set();
let finalResult = null;
for (const [index, rawLine] of String(text).split(/\r?\n/).entries()) {
const line = rawLine.trim();
if (!line) continue;
let event;
try {
event = JSON.parse(line);
} catch {
throw new Error(`Invalid Claude evidence JSON at line ${index + 1}`);
}
if (event?.type === "system" && event?.subtype === "init") {
for (const command of Array.isArray(event.slash_commands) ? event.slash_commands : []) {
slashCommands.add(String(command));
}
for (const skill of Array.isArray(event.skills) ? event.skills : []) {
skills.add(String(skill));
}
}
for (const block of contentBlocks(event)) {
if (block?.type === "tool_use" && typeof block.id === "string") {
toolUses.set(block.id, { name: String(block.name || ""), input: block.input || {} });
}
if (
block?.type === "tool_result" &&
typeof block.tool_use_id === "string" &&
block.is_error !== true
) {
successfulResults.add(block.tool_use_id);
}
}
if (event?.type === "result") finalResult = event;
}
if (!finalResult || finalResult.subtype !== "success" || finalResult.is_error === true) {
throw new Error("Claude evidence has no successful terminal result");
}
const resultText = String(finalResult.result || "");
const incompleteResult = [
/(?:^|\n)\s*(?:\*\*)?blocker(?:\*\*)?\s*:/im,
/\btask (?:is|remains) (?:not complete|incomplete)\b/i,
/(?:^|\n)\s*(?:[-*]\s*)?(?:\*\*)?next steps? needed(?:\*\*)?\s*:/im,
].some((pattern) => pattern.test(resultText));
if (incompleteResult) {
throw new Error("Claude terminal result explicitly reports incomplete work");
}
if (options?.requiredSlashCommand && !slashCommands.has(options.requiredSlashCommand)) {
throw new Error(`Claude did not load required slash command: ${options.requiredSlashCommand}`);
}
if (options?.requiredSkill && !skills.has(options.requiredSkill)) {
throw new Error(`Claude did not load required skill: ${options.requiredSkill}`);
}
const markerIsStandalone = resultText.split(/\r?\n/).some((line) => line.trim() === marker);
for (const requiredTool of requiredTools) {
if (![...toolUses.values()].some((tool) => tool.name === requiredTool)) {
throw new Error(`Claude did not request required client-owned tool: ${requiredTool}`);
}
}
const npmTestSucceeded = [...toolUses.entries()].some(
([id, tool]) =>
tool.name === "Bash" &&
/\bnpm\s+test\b/.test(String(tool.input?.command || "")) &&
successfulResults.has(id)
);
if (options?.requireSuccessfulNpmTest) {
if (!npmTestSucceeded) throw new Error("Claude evidence has no successful npm test tool turn");
}
const markerIsCorroborated =
options?.requireSuccessfulNpmTest && npmTestSucceeded && resultText.includes(marker);
const explicitCompletionIsCorroborated =
options?.acceptExplicitCompletion === true &&
npmTestSucceeded &&
/\btask is complete\b/i.test(resultText);
if (!markerIsStandalone && !markerIsCorroborated && !explicitCompletionIsCorroborated) {
throw new Error(`Claude result has no standalone marker: ${marker}`);
}
}
if (process.argv[1] && pathToFileURL(process.argv[1]).href === import.meta.url) {
const [
evidencePath,
marker,
requiredTools = "",
requireNpmTest = "false",
requiredSlashCommand = "",
requiredSkill = "",
acceptExplicitCompletion = "false",
] = process.argv.slice(2);
if (!evidencePath)
throw new Error("Usage: validate-claude-evidence.mjs FILE MARKER [TOOLS] [NPM_TEST]");
validateClaudeEvidenceText(fs.readFileSync(evidencePath, "utf8"), {
marker,
requiredTools: requiredTools
.split(",")
.map((value) => value.trim())
.filter(Boolean),
requireSuccessfulNpmTest: requireNpmTest === "true",
requiredSlashCommand: requiredSlashCommand || undefined,
requiredSkill: requiredSkill || undefined,
acceptExplicitCompletion: acceptExplicitCompletion === "true",
});
process.stdout.write(`PASS: validated Claude evidence for ${marker}\n`);
}

View File

@@ -0,0 +1,259 @@
#!/usr/bin/env bash
set -euo pipefail
source "$(dirname "$0")/common"
fail() { printf 'FAIL: %s\n' "$1" >&2; exit 1; }
bridge_prepare_sandbox
compose_config=(docker compose -f "$BRIDGE_COMPOSE" --env-file /dev/null --profile offline --profile live-devin config)
config="$("${compose_config[@]}")"
config_json="$("${compose_config[@]}" --format json)"
for forbidden in "$HOME/.claude" "$HOME/.claude.json" "$HOME/.ssh" "/var/run/docker.sock"; do
[[ "$config" != *"$forbidden"* ]] || fail "forbidden host mount appears in compose: $forbidden"
done
grep -q 'user: 10001:10001' <<<"$config" || fail "runtime is not non-root"
grep -q 'read_only: true' <<<"$config" || fail "runtime root filesystem is not read-only"
grep -q 'internal: true' <<<"$config" || fail "internal network is missing"
grep -q 'CLAUDE_CONFIG_DIR: /home/bridge/.claude-devin-isolated' <<<"$config" || fail "isolated Claude config is missing"
node -e '
const fs = require("node:fs");
const config = JSON.parse(fs.readFileSync(0, "utf8"));
const liveNetworks = Object.keys(config.services["omniroute-live"].networks || {}).sort();
if (JSON.stringify(liveNetworks) !== JSON.stringify(["bridge-internal", "devin-guard-internal"])) {
throw new Error(`live runtime network escape: ${liveNetworks.join(",")}`);
}
const guardNetworks = Object.keys(config.services["network-guard"].networks || {}).sort();
if (JSON.stringify(guardNetworks) !== JSON.stringify(["devin-guard-internal", "guard-egress"])) {
throw new Error(`network guard topology mismatch: ${guardNetworks.join(",")}`);
}
const claudeGuard = config.services["claude-egress-guard"];
if (JSON.stringify(Object.keys(claudeGuard.networks || {})) !== JSON.stringify(["bridge-internal"])) {
throw new Error("Claude egress guard must remain on the internal network only");
}
if (config.services["network-guard"].environment.GUARD_POLICY !== "devin") {
throw new Error("Devin network guard policy mismatch");
}
if (claudeGuard.environment.GUARD_POLICY !== "deny-all") {
throw new Error("Claude egress guard is not deny-all");
}
for (const guardName of ["network-guard", "claude-egress-guard"]) {
const guard = config.services[guardName];
const env = config.services[guardName].environment;
if (env.GUARD_ALLOW_SUFFIXES || env.GUARD_ALLOW_HOSTS) {
throw new Error(`${guardName} exposes mutable host allowlists`);
}
if (!guard.healthcheck?.test) throw new Error(`${guardName} has no healthcheck`);
const auditMount = (guard.volumes || []).find((mount) => mount.target === "/guard-audit");
if (!auditMount || auditMount.type !== "bind" || !auditMount.source.includes("/.sandbox/guard-audit/")) {
throw new Error(`${guardName} does not use its guard-only audit bind`);
}
}
const runtimeNames = ["omniroute", "claude", "contract", "omniroute-live", "claude-live"];
for (const serviceName of [...runtimeNames, "network-guard", "claude-egress-guard"]) {
const service = config.services[serviceName];
if (String(service.user) !== "10001:10001" || !service.read_only) {
throw new Error(`${serviceName} is not non-root and read-only`);
}
}
for (const serviceName of runtimeNames) {
const service = config.services[serviceName];
if ((service.volumes || []).some((mount) => mount.target === "/guard-audit")) {
throw new Error(`${serviceName} can mutate guard audit evidence`);
}
const namedVolumes = (service.volumes || []).filter((mount) => mount.type === "volume");
const hasClaudeConfig = namedVolumes.some(
(mount) => mount.target === "/home/bridge/.claude-devin-isolated",
);
const hasDevinAuth = namedVolumes.some(
(mount) => mount.target === "/home/bridge/.local/share/devin",
);
const expectsClaudeConfig = serviceName === "claude" || serviceName === "claude-live";
const expectsDevinAuth = serviceName === "omniroute-live";
if (hasClaudeConfig !== expectsClaudeConfig) {
throw new Error(`${serviceName} Claude config volume ownership mismatch`);
}
if (hasDevinAuth !== expectsDevinAuth) {
throw new Error(`${serviceName} Devin auth volume ownership mismatch`);
}
for (const key of [
"ANTHROPIC_MODEL",
"ANTHROPIC_DEFAULT_SONNET_MODEL",
"ANTHROPIC_DEFAULT_OPUS_MODEL",
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
"CLAUDE_CODE_SUBAGENT_MODEL",
]) {
if (!String(service.environment[key] || "").startsWith("devin-cli-agentic/")) {
throw new Error(`${serviceName} has a non-Devin model alias in ${key}`);
}
}
}
if (config.services["omniroute-live"].depends_on["network-guard"].condition !== "service_healthy") {
throw new Error("omniroute-live does not wait for a healthy Devin guard");
}
for (const serviceName of ["claude", "claude-live"]) {
if (config.services[serviceName].depends_on["claude-egress-guard"].condition !== "service_healthy") {
throw new Error(`${serviceName} does not wait for a healthy Claude guard`);
}
}
const liveEnv = config.services["omniroute-live"].environment;
if (liveEnv.DEVIN_BRIDGE_PROXY_URL !== "http://network-guard:8080") {
throw new Error("trusted Devin bridge proxy is missing");
}
for (const key of ["HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY"]) {
if (liveEnv[key]) throw new Error(`omniroute-live must not inherit ${key}`);
}
for (const serviceName of runtimeNames.filter((name) => name !== "omniroute-live")) {
if (config.services[serviceName].environment.DEVIN_BRIDGE_PROXY_URL) {
throw new Error(`${serviceName} received the Devin bridge proxy setting`);
}
}
for (const serviceName of ["claude", "claude-live"]) {
const env = config.services[serviceName].environment;
if (
env.NODE_USE_ENV_PROXY !== "1" ||
env.HTTP_PROXY !== "http://claude-egress-guard:8080" ||
env.HTTPS_PROXY !== "http://claude-egress-guard:8080" ||
env.NO_PROXY !== "omniroute"
) {
throw new Error(`${serviceName} does not use the deny-all Claude guard`);
}
if (env.HTTP_PROXY === "http://network-guard:8080") {
throw new Error(`${serviceName} received the Devin-capable guard`);
}
}
' <<<"$config_json" || fail "structured compose isolation checks failed"
node --input-type=module -e '
import { pathToFileURL } from "node:url";
const policy = await import(pathToFileURL(process.argv[1]));
const allowed = [
"devin.ai",
"api.devin.ai",
"cognition.ai",
"api.cognition.ai",
"server.codeium.com",
"unleash.codeium.com",
];
const denied = [
"evildevin.ai",
"codeium.com",
"api.codeium.com",
"o123.ingest.sentry.io",
"api.anthropic.com",
"claude.ai",
];
for (const hostname of allowed) {
if (!policy.isAllowedGuardHostname(hostname, "devin")) throw new Error(`denied ${hostname}`);
}
for (const hostname of denied) {
if (policy.isAllowedGuardHostname(hostname, "devin")) throw new Error(`allowed ${hostname}`);
}
if (policy.isAllowedGuardHostname("api.devin.ai", "deny-all")) {
throw new Error("deny-all guard allowed Devin traffic");
}
' "$BRIDGE_ROOT/docker/devin-bridge/network-guard/policy.mjs" || fail "network guard policy checks failed"
bridge_test_env node --import tsx/esm --input-type=module -e '
import { pathToFileURL } from "node:url";
const { buildDevinChildEnv } = await import(pathToFileURL(process.argv[1]));
const home = process.env.DEVIN_AGENTIC_HOME;
const trusted = buildDevinChildEnv({}, {
DEVIN_AGENTIC_HOME: home,
DEVIN_BRIDGE_PROXY_URL: "http://network-guard:8080",
HTTP_PROXY: "http://user:password@host-proxy.example:3128",
HTTPS_PROXY: "http://user:password@host-proxy.example:3128",
ALL_PROXY: "socks5://host-proxy.example:1080",
});
if (
trusted.HTTP_PROXY !== "http://network-guard:8080" ||
trusted.HTTPS_PROXY !== "http://network-guard:8080" ||
trusted.ALL_PROXY
) {
throw new Error("trusted child proxy derivation failed");
}
const untrusted = buildDevinChildEnv({}, {
DEVIN_AGENTIC_HOME: home,
DEVIN_BRIDGE_PROXY_URL: "http://user:password@network-guard:8080",
HTTP_PROXY: "http://host-proxy.example:3128",
});
if (untrusted.HTTP_PROXY || untrusted.HTTPS_PROXY) {
throw new Error("untrusted child proxy was inherited");
}
' "$BRIDGE_ROOT/open-sse/executors/devin-cli-agentic.ts" || \
fail "Devin child proxy boundary checks failed"
bridge_assert_devin_auth_status 0 $'Logged in (via Devin)\n' || fail "clean auth fixture was rejected"
if bridge_assert_devin_auth_status 0 $'Logged in (via Devin)\nFailed to fetch from server\n' 2>/dev/null; then
fail "server-fetch auth failure was accepted"
fi
if bridge_assert_devin_auth_status 0 $'Logged out\n' 2>/dev/null; then
fail "logged-out auth fixture was accepted"
fi
if bridge_assert_devin_auth_status 0 $'Not Logged in (via Devin)\n' 2>/dev/null; then
fail "misleading auth fixture was accepted"
fi
selected_model="$(printf '%s' '{"models":[{"family_uid":"swe-1.7"},{"modelUid":"swe-1.7-lightning"}]}' | \
node --import tsx/esm "$BRIDGE_ROOT/scripts/devin-bridge/select-live-model.mjs")"
[[ "$selected_model" == swe-1-7-lightning ]] || fail "live model normalization or preference failed"
if printf '%s' '{"models":[{"family_uid":"unknown.9"}]}' | \
node --import tsx/esm "$BRIDGE_ROOT/scripts/devin-bridge/select-live-model.mjs" >/dev/null 2>&1; then
fail "unknown normalized live model was accepted"
fi
grep -q 'bridge_run_devin auth login --force-manual-token-flow' \
"$BRIDGE_ROOT/scripts/devin-bridge/login-devin" || fail "manual token login flow is missing"
if grep -Eqi 'read[[:space:]].*token|printf[[:space:]].*token|echo[[:space:]].*token' \
"$BRIDGE_ROOT/scripts/devin-bridge/login-devin"; then
fail "login script could expose a token"
fi
grep -q 'bridge_check_devin_auth' "$BRIDGE_ROOT/scripts/devin-bridge/test-live-devin" || \
fail "live test bypasses strict auth status"
grep -q 'bridge_check_devin_auth' "$BRIDGE_ROOT/scripts/devin-bridge/launch" || \
fail "normal launch bypasses strict auth status"
grep -q 'up -d --wait network-guard claude-egress-guard' "$BRIDGE_ROOT/scripts/devin-bridge/launch" || \
fail "normal launch does not start the audited Claude egress guard"
grep -qx '\.sandbox' "$BRIDGE_ROOT/.dockerignore" || fail ".sandbox is not excluded from builds"
if [[ "${1:-}" == --static ]]; then printf 'PASS: static bridge isolation checks passed\n'; exit 0; fi
trap bridge_cleanup_compose EXIT
bridge_cleanup_compose
bridge_reset_claude_egress_audit
docker compose -f "$BRIDGE_COMPOSE" --profile offline up -d --wait claude-egress-guard
docker compose -f "$BRIDGE_COMPOSE" --profile offline run --rm --no-deps claude bash -ceu '
test "$(id -u)" = 10001
test "$HOME" = /home/bridge
test "$CLAUDE_CONFIG_DIR" = /home/bridge/.claude-devin-isolated
test "$ANTHROPIC_BASE_URL" = http://omniroute:20128
test "$ANTHROPIC_AUTH_TOKEN" = sk-local-devin-gateway
test -z "${ANTHROPIC_API_KEY:-}${CLAUDE_CODE_OAUTH_TOKEN:-}${AWS_ACCESS_KEY_ID:-}${AWS_SECRET_ACCESS_KEY:-}${GOOGLE_APPLICATION_CREDENTIALS:-}${AZURE_OPENAI_API_KEY:-}"
test ! -e /var/run/docker.sock
if touch /bridge-must-remain-read-only 2>/dev/null; then
echo "container root filesystem is writable" >&2; exit 1
fi
for host in api.anthropic.com claude.ai; do
if node -e "require(\"net\").connect(443,process.argv[1]).on(\"connect\",()=>process.exit(0)).on(\"error\",()=>process.exit(1)).setTimeout(1500,()=>process.exit(1))" "$host"; then
echo "unexpected network access to $host" >&2; exit 1
fi
done
'
docker compose -f "$BRIDGE_COMPOSE" --profile offline run --rm --no-deps claude \
node --input-type=module -e '
async function expectProxyDenial(request) {
try {
const response = await request;
if (response.status !== 403) {
throw new Error(`unexpected proxy response: ${response.status}`);
}
} catch (error) {
if (error instanceof Error && error.message.startsWith("unexpected proxy response:")) {
throw error;
}
}
}
await expectProxyDenial(fetch("https://api.anthropic.com", {
signal: AbortSignal.timeout(3000),
}));
await expectProxyDenial(fetch("https://claude.ai", {
signal: AbortSignal.timeout(3000),
}));
'
bridge_cleanup_compose
bridge_assert_claude_guard_denials "$BRIDGE_CLAUDE_AUDIT" || \
fail "Claude proxy denial audit proof failed"
bridge_export_guard_audit "$BRIDGE_CLAUDE_AUDIT" claude-egress-verifier.jsonl
trap - EXIT
bridge_reset_claude_egress_audit
printf 'PASS: runtime bridge isolation checks passed\n'