"""send_file (§34 / UX-016): deliverables into the chat, with its own approval surface. Gates: happy path via a fake FileSender (no network) · path containment against workspace/roots · unsupported platform · missing token · as_screenshot HTML-only with an injected renderer · and the permission split — a thread's standing send_message grant must NEVER cover send_file. """ from pathlib import Path from coworker.connectors.base import SendResult from coworker.connectors.tools import make_send_file_tool from coworker.permissions import Mode, PermissionEngine from coworker.roots import RootDir from coworker.secrets import SecretStore def _secrets(tmp_path, token="xoxb-1") -> SecretStore: s = SecretStore(tmp_path / "secrets.json") if token: s.put("slack:default", {"bot_token": token, "enabled": True}) return s def _fake_sender(record: list): def sender(token, chat_id, thread_id, filename, data, title, comment): record.append( { "token": token, "chat_id": chat_id, "thread_id": thread_id, "filename": filename, "data": data, "title": title, "comment": comment, } ) return SendResult(True, message_id="F123") return {"slack": sender} def test_send_file_success_within_workspace(tmp_path): ws = tmp_path / "ws" ws.mkdir() (ws / "report.pdf").write_bytes(b"%PDF-fake") record: list = [] tool = make_send_file_tool( _secrets(tmp_path), workspace=ws, file_senders=_fake_sender(record) ) out = tool("slack:C9:1700.1", "report.pdf", comment="here you go") assert out == { "ok": True, "file_id": "F123", "target": "slack:C9:1700.1", "filename": "report.pdf", } sent = record[0] assert sent["chat_id"] == "C9" and sent["thread_id"] == "1700.1" assert sent["data"] == b"%PDF-fake" and sent["comment"] == "here you go" def test_send_file_rejects_paths_outside_roots(tmp_path): ws = tmp_path / "ws" ws.mkdir() outside = tmp_path / "elsewhere.txt" outside.write_text("secret") tool = make_send_file_tool( _secrets(tmp_path), workspace=ws, file_senders=_fake_sender([]) ) # Absolute path outside every base, and a traversal attempt — both refused. assert "error" in tool("slack:C9", str(outside)) assert "error" in tool("slack:C9", "../elsewhere.txt") def test_send_file_roots_extend_the_reachable_set(tmp_path): ws = tmp_path / "ws" ws.mkdir() shared = tmp_path / "shared" shared.mkdir() (shared / "data.csv").write_text("a,b\n1,2\n") record: list = [] tool = make_send_file_tool( _secrets(tmp_path), workspace=ws, roots=[RootDir(path=shared)], file_senders=_fake_sender(record), ) out = tool("slack:C9", str(shared / "data.csv")) assert out["ok"] and record[0]["filename"] == "data.csv" def test_send_file_unsupported_platform_and_missing_token(tmp_path): ws = tmp_path / "ws" ws.mkdir() (ws / "a.txt").write_text("x") tool = make_send_file_tool( _secrets(tmp_path), workspace=ws, file_senders=_fake_sender([]) ) assert "not supported" in tool("telegram:123", "a.txt")["error"] no_token = make_send_file_tool( _secrets(tmp_path / "nt", token=None), workspace=ws, file_senders=_fake_sender([]), ) assert "no bot token" in no_token("slack:C9", "a.txt")["error"] def test_send_file_screenshot_is_html_only_and_renames_to_png(tmp_path): ws = tmp_path / "ws" ws.mkdir() (ws / "dash.html").write_text("