Files
cowork-local/tests/conftest.py
T
minhanhpkproandClaude Opus 5 b78d48320c fix(sandbox): "Chặn mạng" chặn mọi đường ra mạng, trừ nhà cung cấp AI
Trước đây công tắc chỉ chặn tool mạng của agent; lệnh shell chỉ bị proxy
giả, còn M365, Teams, nút Test, MCP đang chạy, task script, link đính kèm
task, pip tự cài và tài nguyên web trong xem trước HTML vẫn ra mạng tự do.

- Cổng chung application/network/network_guard.py, nối vào cấu hình sống
  ở Composition Root; nhà cung cấp AI (chat, danh sách model, thử model)
  không đi qua cổng này.
- Lệnh shell của agent và task script chạy trong Windows AppContainer
  không có quyền mạng (macOS: sandbox-exec, Linux: unshare --net);
  không cô lập được thì từ chối chạy.
- Không cấp quyền kế thừa của AppContainer lên thư mục chứa PySide6:
  Chromium không nạp được Qt6WebEngineCore.dll và tab Graph bị hỏng.
- Bật chặn thì dừng MCP đang chạy; tool OneDrive đồng bộ trên máy vẫn dùng.
- Mặc định tắt khi mở app lần đầu; nhãn và tooltip 3 ngôn ngữ cập nhật.
- Test: tests/test_network_guard_lanes.py (có bài AppContainer thật).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 22:32:44 +09:00

90 lines
3.7 KiB
Python

"""Make THIS checkout importable as the ``cowork_local`` package during tests.
Why this is not just a ``sys.path`` insert
------------------------------------------
Test modules import the app in two different styles:
* top-level (``from providers.base import ...``) — resolved by the repository
root already sitting on ``sys.path`` when pytest is launched from it;
* fully qualified (``from cowork_local.core.routing.service import ...``) —
which only resolves when a directory literally named ``cowork_local`` is
importable.
Simply appending the repository's PARENT directory to ``sys.path`` (the previous
behaviour) makes the second style resolve against *whatever* sibling folder
happens to be called ``cowork_local`` — on a developer machine that is often an
unrelated older checkout, so the whole suite silently exercises the wrong code
while still reporting green. Instead we bind the name ``cowork_local`` in
``sys.modules`` to the package rooted at THIS repository, so both import styles
always reach the working copy under test regardless of the checkout's directory
name.
"""
from __future__ import annotations
import importlib.util
import sys
from pathlib import Path
# .../<checkout>/tests/conftest.py -> .../<checkout>
PACKAGE_ROOT = Path(__file__).resolve().parents[1]
PACKAGE_NAME = "cowork_local"
# The repository root must stay importable so the top-level import style
# (``providers``/``domain``/``application``/``tests``) keeps working.
if str(PACKAGE_ROOT) not in sys.path:
sys.path.insert(0, str(PACKAGE_ROOT))
def _bind_checkout_as_package() -> None:
"""Register this checkout in ``sys.modules`` under the canonical package name.
Executed at import time of the conftest (i.e. before any test module is
imported) so that a stale same-named directory elsewhere on ``sys.path`` can
never win the lookup. A no-op when the package is already bound to this very
directory, which keeps repeated conftest loads (pytest-xdist, sub-sessions)
idempotent.
"""
existing = sys.modules.get(PACKAGE_NAME)
if existing is not None:
# Already bound. Only rebind when it points at a DIFFERENT checkout,
# otherwise re-executing the package __init__ would duplicate module
# state that tests may already hold references to.
origin = getattr(existing, "__file__", "") or ""
if Path(origin).resolve().parent == PACKAGE_ROOT:
return
spec = importlib.util.spec_from_file_location(
PACKAGE_NAME,
PACKAGE_ROOT / "__init__.py",
# Declaring the search locations is what turns the module into a real
# package, so ``cowork_local.core.routing`` and friends resolve as
# sub-modules of this directory.
submodule_search_locations=[str(PACKAGE_ROOT)],
)
if spec is None or spec.loader is None: # pragma: no cover — defensive
return
module = importlib.util.module_from_spec(spec)
# Insert BEFORE executing so that a circular ``import cowork_local`` from
# inside the package body resolves to the partially-initialised module
# instead of restarting the import (standard CPython import semantics).
sys.modules[PACKAGE_NAME] = module
spec.loader.exec_module(module)
_bind_checkout_as_package()
import pytest # noqa: E402 - after the package binding above
@pytest.fixture(autouse=True)
def _reset_network_guard():
"""``build_context()`` binds the process-wide "Block network" gate to that
context's config (default: blocked). Unbind after every test so one test
that built a real context cannot silently block the network for the rest."""
yield
from cowork_local.application.network import network_guard
network_guard.bind(None)