fix(harness): ship coherent vendor harness cluster

Rebuild PR C to ship the vendor/photocraft harness as a coherent unit
(vendor implementation + vendor tests) instead of a per-file ahead/behind
mix that produced broken imports and 6+ test failures.

- Flip 36 harness impl/route/test files back to vendor (the per-file
  line-set policy misclassified user-rewritten files as 'behind').
- Flip core/models.py + src/tool_approval_scopes.py to vendor: vendor's
  harness (authority.py, turn_contract.py, clean_agent_preview.py) depends
  on vendor's older approval-scope API; upstream added
  CHAT_SESSION_APPROVAL_SIGNATURE_FIELD that vendor's core/models.py lacks.
- Add src/shutdown.py (new vendor infra) required by routes/chat_routes.py.
- Keep src/agent_tools/__init__.py at upstream (editor_tools registration
  lives in PR B).

Upstream-only security divergence preserved in C_upstream_delta.patch and
flagged for integration-time reconciliation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
pewdiepie-archdaemon
2026-10-13 13:59:04 +00:00
co-authored by Claude Opus 5.5
parent 364229f2dc
commit 9bdea753ae
39 changed files with 804 additions and 3076 deletions
+1 -2
View File
@@ -1873,8 +1873,7 @@ def test_tui_local_skill_request_reconciles_normal_tool_policy(monkeypatch):
},
)))
# Caller hard denials are absolute and cannot be re-enabled by later TUI turn contracts.
assert calls == []
assert calls == ["manage_skills"]
assert not any(e.get("type") == "loop_breaker_triggered" for e in events)
+2 -3
View File
@@ -49,9 +49,8 @@ def test_scheduler_fallbacks_and_research_headers_are_owner_scoped():
assert "owner=task.owner or None" in src
assert "headers_from_resolver = False" in src
assert "headers_from_resolver = True" in src
assert "resolve_owner_registered_endpoint(db2, endpoint_url, task.owner or None)" in src
assert "resolve_owner_registered_endpoint(db, endpoint_url, task.owner or None)" in src
assert src.count("resolve_endpoint_runtime(ep, owner=task.owner or None)") == 2
assert "from src.auth_helpers import owner_filter" in src
assert "owner_filter(ep_q, ModelEndpoint, task.owner or None)" in src
def test_research_routes_fallbacks_are_owner_scoped():
+12 -34
View File
@@ -49,6 +49,9 @@ async def _create_with_reminder(reminder, owner):
@pytest.mark.parametrize("reminder,expected", [
(0, 0), # At-event reminder must not compare equal to False.
(0.0, 0),
("0", 0),
("5 mins", 5),
("10 mins", 10),
("2 hrs", 120),
@@ -91,6 +94,15 @@ async def test_no_reminder_when_offset_absent():
assert "reminder set" not in res.get("response", ""), res
@pytest.mark.parametrize("reminder", [False, "off", "false", None])
async def test_disabled_reminder_is_distinct_from_zero(reminder):
owner = "tester-" + uuid.uuid4().hex[:6]
res = await _create_with_reminder(reminder, owner)
assert res.get("exit_code") == 0, res
assert not res.get("has_reminder"), res
assert res.get("reminder_note_id") is None, res
async def test_update_event_can_add_reminder_after_creation():
owner = "tester-" + uuid.uuid4().hex[:6]
from src.tool_implementations import do_manage_calendar
@@ -123,37 +135,3 @@ async def test_update_event_can_add_reminder_after_creation():
assert note is not None, "update_event should create the reminder note"
finally:
db.close()
async def test_reminder_and_duration_parsers_stay_linear_on_digit_and_space_floods():
"""CodeQL py/polynomial-redos: `(\\d+)\\s*unit` rescanned a digit run from
every offset and `alarm\\s*:?\\s*\\d+` split one whitespace run two ways.
Tool arguments come from model output, so keep them O(n)."""
import time
from src.tool_implementations import do_manage_calendar
owner = "tester-" + uuid.uuid4().hex[:6]
started = time.perf_counter()
res = await do_manage_calendar(json.dumps({
"action": "create_event",
"summary": "Flood",
"dtstart": "2030-04-01T10:00:00",
"reminder_minutes": "0" * 40_000 + "x",
"duration": "0" * 40_000 + "x",
}), owner=owner)
assert time.perf_counter() - started < 2.0
assert res.get("exit_code") == 0, res
assert "reminder set" not in res.get("response", ""), res
# A reminder is set, so the "is the description only a reminder?" check runs.
started = time.perf_counter()
res = await do_manage_calendar(json.dumps({
"action": "create_event",
"summary": "Flood 2",
"dtstart": "2030-04-02T10:00:00",
"description": "alarm" + "\t" * 40_000,
"reminder_minutes": 5,
}), owner=owner)
assert time.perf_counter() - started < 2.0
assert res.get("exit_code") == 0, res
assert "reminder 5 min before" in res.get("response", ""), res
+11 -12
View File
@@ -624,8 +624,7 @@ def test_bridge_post_targets_endpoint_paths():
posted = {}
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
posted["timeout"] = timeout
async def __aenter__(self):
@@ -696,8 +695,8 @@ def test_bridge_post_treats_empty_or_error_payload_as_failure():
payloads = iter(({}, {"error": "token rejected"}))
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
pass
async def __aenter__(self):
return self
@@ -735,8 +734,8 @@ def test_bridge_post_http_or_payload_error_overrides_false_success_code():
))
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
pass
async def __aenter__(self):
return self
@@ -770,8 +769,8 @@ def test_bridge_post_rejects_malformed_exit_code():
return {"output": "looks successful", "exit_code": "zero"}
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
pass
async def __aenter__(self):
return self
@@ -805,8 +804,8 @@ def test_bridge_post_reports_empty_invalid_json_response():
raise ValueError("not JSON")
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
pass
async def __aenter__(self):
return self
@@ -834,8 +833,8 @@ def test_bridge_post_reports_empty_invalid_json_response():
def test_bridge_post_cancellation_schedules_host_operation_cancel():
class FakeClient:
def __init__(self, timeout=None, *, trust_env=True):
assert trust_env is False
def __init__(self, timeout=None):
pass
async def __aenter__(self):
return self
+1 -21
View File
@@ -61,20 +61,11 @@ def test_grep_ignore_case(repo):
assert "b.txt:2:" in r["output"]
def test_grep_glob_filter(repo, monkeypatch):
def test_grep_glob_filter(repo):
r = _run("grep", f'{{"pattern": "needle", "ignore_case": true, "glob": "*.py", "path": "{repo}"}}')
assert r["exit_code"] == 0
assert "a.py" in r["output"]
assert "b.txt" not in r["output"]
# Positive control: verify that fallback path honors the exact same glob contract
real_which = shutil.which
monkeypatch.setattr(shutil, "which", lambda name, *a, **kw: None if name == "rg" else real_which(name, *a, **kw))
r_fallback = _run("grep", f'{{"pattern": "needle", "ignore_case": true, "glob": "*.py", "path": "{repo}"}}')
assert r_fallback["exit_code"] == 0
assert "a.py" in r_fallback["output"]
assert "b.txt" not in r_fallback["output"]
def test_grep_no_match(repo):
r = _run("grep", f'{{"pattern": "zzzznotfound", "path": "{repo}"}}')
@@ -103,17 +94,6 @@ def test_grep_python_fallback_when_no_rg(repo, monkeypatch):
assert ".git/config" not in r["output"]
def test_grep_python_fallback_uses_relative_glob_paths(repo, monkeypatch):
monkeypatch.setattr(shutil, "which", lambda name: None)
r = _run(
"grep",
f'{{"pattern": "needle|python", "glob": "**/*.py", "path": "{repo}"}}',
)
assert r["exit_code"] == 0
assert "a.py" in r["output"]
assert "sub/deep/c.py" in r["output"]
@pytest.mark.skipif(shutil.which("rg") is None, reason="targets the ripgrep fast-path")
def test_grep_skips_case_variant_sensitive_files_rg(repo):
"""The rg fast-path must exclude deny-listed key files case-insensitively.
+1 -9
View File
@@ -179,16 +179,8 @@ def test_cancelled_write_unsettles_an_earlier_success(run, ws, monkeypatch):
def test_mid_write_failure_unsettles_but_refusal_preserves(run, ws, monkeypatch):
run("write_file", {"path": "a.txt", "content": "hello\n"})
# Explicit empty JSON clear/write is authoritative and succeeds.
run("write_file", {"path": "a.txt", "content": ""})
assert run.journal.effects.assessments()[-1].execution is fx.ExecutionOutcome.REPORTED_SUCCESS
# Re-seed the artifact content
run("write_file", {"path": "a.txt", "content": "hello\n"})
assert ledger(run.journal, ws).evaluate().can_complete
# A deterministic refusal before the mutation stage keeps the artifact.
run("write_file", "a.txt\n")
run("write_file", {"path": "a.txt", "content": ""})
assert run.journal.effects.assessments()[-1].execution is fx.ExecutionOutcome.FAILED
assert ledger(run.journal, ws).evaluate().can_complete
+1 -47
View File
@@ -167,56 +167,10 @@ def test_renders_one_table_row_per_variable(generator, fake_tree, monkeypatch):
page = generator.render(found, generator.naive_line_scan(fake_tree))
assert page.startswith("---\nlayout: default\n---\n")
assert "| `ODYSSEUS_VIA_HELPER` | `5 * 1024` | `src/indirect.py` | A synthetic limit. |" in page
assert "| `ODYSSEUS_VIA_HELPER` | `5 * 1024` | `src/indirect.py:16` | A synthetic limit. |" in page
assert "### Search" in page
def _render_one(generator, root, name, monkeypatch):
monkeypatch.setitem(
generator.VARIABLE_NOTES, name, ("Search", generator.USER, "A synthetic flag.")
)
return generator.render(
{name: generator.collect(root)[name]}, generator.naive_line_scan(root)
)
def test_page_does_not_change_when_an_unrelated_edit_shifts_lines(
generator, fake_tree, monkeypatch
):
"""An edit that moves a read down a file must not make the page stale.
The page used to cite `path:line`, so any PR adding a line above a read had
to regenerate it and then conflicted with every other PR that had.
"""
before = _render_one(generator, fake_tree, "ODYSSEUS_VIA_HELPER", monkeypatch)
source = fake_tree / "src" / "indirect.py"
source.write_text("import sys\n\n\n" + source.read_text(encoding="utf-8"), encoding="utf-8")
after = _render_one(generator, fake_tree, "ODYSSEUS_VIA_HELPER", monkeypatch)
assert generator.collect(fake_tree)["ODYSSEUS_VIA_HELPER"].primary.lineno == 19
assert after == before
def test_extra_reads_are_counted_per_file(generator, tmp_path, monkeypatch):
monkeypatch.setattr(generator, "SOURCE_ROOTS", ("app.py", "src"))
_write(tmp_path, "app.py", """
import os
FIRST = os.environ.get("ODYSSEUS_READ_OFTEN", "1")
SECOND = os.environ.get("ODYSSEUS_READ_OFTEN", "1")
""")
_write(tmp_path, "src/elsewhere.py", """
import os
AGAIN = os.getenv("ODYSSEUS_READ_OFTEN")
""")
page = _render_one(generator, tmp_path, "ODYSSEUS_READ_OFTEN", monkeypatch)
assert "| `app.py` (+1 more) |" in page
def test_every_variable_read_in_the_repository_is_documented(built):
_, variables, problems = built
+7 -68
View File
@@ -1,6 +1,4 @@
import asyncio
import json
import pytest
import logging
import src.tool_execution as tool_execution
from tests.runtime_evidence_helpers import server_authorized_executor
@@ -17,60 +15,6 @@ from src.tool_execution import (
execute_tool_block = server_authorized_executor(execute_tool_block)
@pytest.mark.parametrize("content", ['{"path":"/workspace/x"}', '{"path":"/workspace/x","content":null}',
'/workspace/x', '/workspace/x\n', '/workspace/x\n \t',
json.dumps({'path': '/workspace/x.py', 'content': '```python\n\n```'})])
def test_bridge_refuses_missing_or_ambiguous_empty_content(monkeypatch, tmp_path, content):
async def forbidden(*args, **kwargs):
raise AssertionError("ambiguous write reached remote producer")
monkeypatch.setattr(tool_execution, "_client_bridge", lambda context: {"url": "http://bridge", "token": "x"})
monkeypatch.setattr(tool_execution, "_bridge_post", forbidden)
async def invoke():
token = tool_execution._active_workspace.set(str(tmp_path))
try:
return await tool_execution._route_tool_via_bridge("write_file", content, "s", {})
finally:
tool_execution._active_workspace.reset(token)
_, result = asyncio.run(invoke())
assert result["exit_code"] == 1
assert "content" in result["error"] or "JSON" in result["error"]
@pytest.mark.parametrize("body", ["", " \t", "normal source"])
def test_bridge_honors_explicit_json_string_content(monkeypatch, tmp_path, body):
import base64
seen = []
async def post(bridge, endpoint, payload, **kwargs):
seen.append((endpoint, base64.b64decode(payload["content_b64"])))
return {"output": "written", "exit_code": 0}
monkeypatch.setattr(tool_execution, "_client_bridge", lambda context: {"url": "http://bridge", "token": "x"})
monkeypatch.setattr(tool_execution, "_bridge_post", post)
async def invoke():
token = tool_execution._active_workspace.set(str(tmp_path))
try:
return await tool_execution._route_tool_via_bridge("write_file", json.dumps({"path": "/workspace/x", "content": body}), "s", {})
finally:
tool_execution._active_workspace.reset(token)
_, result = asyncio.run(invoke())
assert result["exit_code"] == 0
assert seen == [("/write", body.encode())]
@pytest.mark.parametrize("content", ['/workspace/x\n', '{"path":"/workspace/x"}', '/workspace/x\n \t'])
def test_scoped_bridge_cannot_blindly_write_implicit_empty(content):
async def forbidden(*args):
raise AssertionError("scoped bridge received an ambiguous destructive write")
bridge = AgentExecutionBridge(forbidden, frozenset({'write_file'}), 'empty-intent-test')
async def invoke():
with bind_execution_bridge(bridge):
block = Block(content)
block.tool_type = 'write_file'
return await execute_tool_block(block, security_context=NO_TOOL_SECURITY_CONTEXT)
_, result = asyncio.run(invoke())
assert result['exit_code'] == 1
assert 'content' in result['error']
class Block:
tool_type = "host_shell"
@@ -215,7 +159,7 @@ def test_scoped_execution_bridge_failure_logs_compact_warning(caplog) -> None:
assert "Scoped execution bridge test-environment failed for tool=host_shell" in caplog.text
def test_tui_bridge_write_file_rejects_text_for_binary_artifact(monkeypatch, tmp_path) -> None:
def test_tui_bridge_write_file_rejects_text_for_binary_artifact(monkeypatch) -> None:
"""The bridge path must preserve rendered media just like local writes."""
called = False
@@ -228,17 +172,12 @@ def test_tui_bridge_write_file_rejects_text_for_binary_artifact(monkeypatch, tmp
monkeypatch.setattr(tool_execution, "_bridge_post", fake_post)
async def invoke():
token = tool_execution._active_workspace.set(str(tmp_path))
try:
return await tool_execution._route_tool_via_bridge(
"write_file",
'{"path":"/tmp_workspace/results/screenshot.png","content":"The screenshot is complete."}',
"run-1",
{"surface": "odysseus-tui"},
)
finally:
tool_execution._active_workspace.reset(token)
return await tool_execution._route_tool_via_bridge(
"write_file",
'{"path":"/tmp_workspace/results/screenshot.png","content":"The screenshot is complete."}',
"run-1",
{"surface": "odysseus-tui"},
)
description, result = asyncio.run(invoke())
+3 -5
View File
@@ -984,7 +984,7 @@ def test_attachment_extract_dir_stays_contained(folder, uid):
"""User-controlled folder/uid must never escape ATTACHMENTS_DIR — pins the
fix for the attachment-extraction path traversal."""
aed, base = _import_attachment_extract_dir()
target = aed(folder, uid, owner="../../owner", account_id="../acct")
target = aed(folder, uid)
base_r = base.resolve()
assert target == base_r or base_r in target.parents
# exactly one extra path segment, and no `..` component survived
@@ -992,11 +992,9 @@ def test_attachment_extract_dir_stays_contained(folder, uid):
assert ".." not in rel.parts
def test_attachment_extract_dir_is_stable_single_segment_per_scope():
def test_attachment_extract_dir_normal_inputs_unchanged():
aed, base = _import_attachment_extract_dir()
target = aed("INBOX", "123", owner="alice", account_id="acct-1")
assert target == aed("INBOX", "123", owner="alice", account_id="acct-1")
assert target.parent == base.resolve()
assert aed("INBOX", "123") == base.resolve() / "INBOX_123"
def test_diagnostics_routes_are_admin_gated():
+3 -52
View File
@@ -6,21 +6,13 @@ from fastapi import HTTPException
# Import the route helper during collection so sibling session tests that use
# partial import stubs do not become the first loader of core.session_manager.
from routes.session_routes import (
_reject_delegated_session_options,
_reject_raw_endpoint_url_for_non_admin,
)
from routes.session_routes import _reject_raw_endpoint_url_for_non_admin
def _request(user, *, admin=False, api_token=False, scopes=None):
def _request(user, *, admin=False):
auth_manager = SimpleNamespace(is_admin=lambda username: bool(admin))
return SimpleNamespace(
state=SimpleNamespace(
current_user="api" if api_token else user,
api_token=api_token,
api_token_owner=user if api_token else None,
api_token_scopes=scopes or [],
),
state=SimpleNamespace(current_user=user),
app=SimpleNamespace(state=SimpleNamespace(auth_manager=auth_manager)),
)
@@ -52,47 +44,6 @@ def test_admin_and_registered_endpoint_can_use_endpoint_url():
)
def test_bearer_token_does_not_inherit_owner_admin_raw_endpoint_authority():
request = _request("admin", admin=True, api_token=True, scopes=["chat"])
with pytest.raises(HTTPException) as exc:
_reject_raw_endpoint_url_for_non_admin(
request,
"admin",
"",
"http://127.0.0.1:8000/v1/chat/completions",
)
assert exc.value.status_code == 403
def test_chat_scoped_bearer_can_still_choose_an_owner_registered_endpoint():
_reject_raw_endpoint_url_for_non_admin(
_request("admin", admin=True, api_token=True, scopes=["chat"]),
"admin",
"owner-endpoint-id",
"http://127.0.0.1:8000/v1/chat/completions",
)
@pytest.mark.parametrize(
("skip_validation", "api_key"),
[(True, ""), (False, "caller-secret")],
)
def test_bearer_token_cannot_use_interactive_session_options(
skip_validation,
api_key,
):
with pytest.raises(HTTPException) as exc:
_reject_delegated_session_options(
_request("admin", admin=True, api_token=True, scopes=["chat"]),
skip_validation=skip_validation,
api_key=api_key,
)
assert exc.value.status_code == 403
def test_chat_endpoint_recovery_paths_are_owner_scoped():
root = Path(__file__).resolve().parents[1]
chat_routes = (root / "routes" / "chat_routes.py").read_text(encoding="utf-8")
+7 -9
View File
@@ -169,14 +169,12 @@ def test_blocks_netrc():
_resolve_tool_path("~/.netrc")
def test_allows_agent_workspace(tmp_path):
"""Paths under the agent's workspace in project data/ must resolve
cleanly. The rest of data/ is application state and is rejected;
tests/test_agent_state_dir_confinement.py covers that side."""
def test_allows_project_data(tmp_path):
"""Paths under project data/ must resolve cleanly."""
from src.tool_execution import _resolve_tool_path
from src.constants import AGENT_WORKSPACE_DIR
target = os.path.join(AGENT_WORKSPACE_DIR, "test-confinement-ok.txt")
os.makedirs(AGENT_WORKSPACE_DIR, exist_ok=True)
from src.constants import DATA_DIR
target = os.path.join(DATA_DIR, "test-confinement-ok.txt")
os.makedirs(DATA_DIR, exist_ok=True)
with open(target, "w") as f:
f.write("ok")
try:
@@ -315,8 +313,8 @@ async def test_write_file_dispatch_rejects_empty_directory_like_workspace_path(m
workspace=str(tmp_path),
security_context=NO_TOOL_SECURITY_CONTEXT,
)
assert "BLOCKED" in desc
assert "content required; missing content section" in (
assert desc == "write_file: /workspace/papers"
assert "content required; refusing to create an empty file" in (
result.get("error") or ""
)
assert result.get("exit_code") == 1
+11 -35
View File
@@ -3,8 +3,6 @@
A stub resolver is injected so the tests never touch real DNS.
"""
import pytest
from src.url_safety import check_outbound_url
@@ -66,39 +64,6 @@ def test_strict_mode_blocks_private_and_loopback():
assert ok is False and "private" in reason
@pytest.mark.parametrize("block_private", [False, True])
@pytest.mark.parametrize("host,ips", [
("127.0.0.1", ["127.0.0.1"]),
("[::1]", ["::1"]),
("[::ffff:127.0.0.1]", ["::ffff:127.0.0.1"]),
("localhost", ["127.0.0.1", "::1"]),
("localhost", ["::1", "127.0.0.1"]),
])
def test_loopback_urls_follow_private_policy(host, ips, block_private):
ok, reason = check_outbound_url(
f"http://{host}:8080", block_private=block_private,
resolver=_resolver({host.strip("[]"): ips}),
)
assert ok is (not block_private), reason
if block_private:
assert "loopback address blocked" in reason
@pytest.mark.parametrize("block_private", [False, True])
@pytest.mark.parametrize("ip", [
"169.254.169.254", "fe80::1", "0.0.0.0", "::", "224.0.0.1", "ff02::1",
"240.0.0.1", "::2", "100::1", "::ffff:169.254.169.254",
"::ffff:0.0.0.0", "::ffff:224.0.0.1", "::ffff:240.0.0.1",
])
def test_special_ranges_stay_blocked_alongside_loopback(ip, block_private):
ok, reason = check_outbound_url(
"http://localhost:8080", block_private=block_private,
resolver=_resolver({"localhost": [ip, "127.0.0.1", "::1"]}),
)
assert ok is False
assert "link-local" in reason or "disallowed address" in reason
def test_strict_mode_blocks_cgnat_shared_space():
# RFC 6598 shared/CGNAT space (100.64.0.0/10) is not globally routable.
# A public redirect into it must be rejected under full SSRF lockdown,
@@ -282,3 +247,14 @@ def test_ordinary_ipv6_behaviour_is_unchanged():
LL6 = _resolver({"ll.example": ["fe80::1"]})
ok, reason = check_outbound_url("http://ll.example/", resolver=LL6)
assert ok is False and "link-local" in reason
# Pre-existing behaviour, unchanged here: CPython reports ::1 as
# is_reserved, so IPv6 loopback is rejected in both modes (unlike 127.0.0.1,
# which the local-first default allows).
LOOP6 = _resolver({"loop6.example": ["::1"]})
for strict in (False, True):
ok, reason = check_outbound_url(
"http://loop6.example/", block_private=strict, resolver=LOOP6
)
assert ok is False, strict
assert "NAT64" not in reason