Files
openworker/tests/test_base_dir.py
Rohit C Prasad 274c9a582b Remote machines: identity, reverse channel, acceptor, sealed key wallet
A machine joins with its own identity and holds a reverse channel to the controller.
Provider keys and connector accounts deploy sealed to the machine's pinned key.
2026-09-05 08:00:16 -07:00

149 lines
7.6 KiB
Python

"""OPENWORKER_BASE_DIR (spec §Fly sandboxes, "Base directory"): a confined box
keeps state and scratch under the base and refuses folders outside it with a
plain error; an unconfined box behaves exactly as before."""
from __future__ import annotations
import os
from pathlib import Path
import pytest
from coworker.basedir import OutsideBaseDir, base_dir, ensure_under_base
from coworker.secrets import state_dir
from coworker.server.manager import SessionManager
def test_unconfined_is_a_no_op(tmp_path, monkeypatch):
monkeypatch.delenv("OPENWORKER_BASE_DIR", raising=False)
assert base_dir() is None
assert ensure_under_base(tmp_path / "anywhere") == (tmp_path / "anywhere").resolve()
def test_confined_paths_resolve_under_base_and_outsiders_are_refused(tmp_path, monkeypatch):
base = tmp_path / "data"
(base / "proj").mkdir(parents=True)
outside = tmp_path / "elsewhere"
outside.mkdir()
monkeypatch.setenv("OPENWORKER_BASE_DIR", str(base))
assert ensure_under_base(base) == base.resolve()
assert ensure_under_base(base / "proj") == (base / "proj").resolve()
with pytest.raises(OutsideBaseDir) as exc:
ensure_under_base(outside, "folder")
assert str(base.resolve()) in str(exc.value) and "folder" in str(exc.value)
# A symlink inside the base pointing out does not slip through.
link = base / "escape"
link.symlink_to(outside)
with pytest.raises(OutsideBaseDir):
ensure_under_base(link)
# `..` tricks neither.
with pytest.raises(OutsideBaseDir):
ensure_under_base(base / ".." / "elsewhere")
def test_state_dir_defaults_under_the_base(tmp_path, monkeypatch):
monkeypatch.delenv("COWORKER_STATE_DIR", raising=False)
monkeypatch.setenv("OPENWORKER_BASE_DIR", str(tmp_path / "data"))
assert state_dir() == tmp_path / "data" / "state"
# An explicit state dir still wins (the image sets both, consistently).
monkeypatch.setenv("COWORKER_STATE_DIR", str(tmp_path / "explicit"))
assert state_dir() == tmp_path / "explicit"
def test_manager_confines_workspaces_scratch_and_roots(tmp_path, monkeypatch):
base = tmp_path / "data"
inside = base / "repo"
inside.mkdir(parents=True)
outside = tmp_path / "home-project"
outside.mkdir()
monkeypatch.setenv("OPENWORKER_BASE_DIR", str(base))
monkeypatch.delenv("COWORKER_SCRATCH_BASE", raising=False)
manager = SessionManager(data_dir=tmp_path / "mgr")
assert manager.open_workspace(str(inside))["ok"] is True
refused = manager.open_workspace(str(outside))
assert refused["ok"] is False and "only works under" in refused["error"]
# Creating a new folder outside is refused before anything is made.
assert manager.open_workspace(str(tmp_path / "new-one"), create=True)["ok"] is False
assert not (tmp_path / "new-one").exists()
assert manager.resolve_workspace(str(inside)) == str(inside.resolve())
assert manager.resolve_workspace(str(outside)) is None
# Scratch lives under the base, and a stray pref cannot move it out.
assert manager.scratch_base() == (base / "workspaces").resolve()
manager._prefs["scratch_base"] = str(outside)
assert manager.scratch_base() == (base / "workspaces").resolve()
scratch = Path(manager._provision_scratch("s-confined"))
assert scratch.is_relative_to(base.resolve())
assert "only works under" in manager.add_root("s-confined", str(outside))["error"]
assert "only works under" in manager.promote_workspace("s-confined", str(outside))["error"]
assert "only works under" in manager.save_temp_as_project("s-confined", str(outside / "saved"))["error"]
def test_unconfined_manager_accepts_any_folder(tmp_path, monkeypatch):
monkeypatch.delenv("OPENWORKER_BASE_DIR", raising=False)
anywhere = tmp_path / "anywhere"
anywhere.mkdir()
manager = SessionManager(data_dir=tmp_path / "mgr")
assert manager.open_workspace(str(anywhere))["ok"] is True
def test_deployed_provider_key_adopts_a_runnable_default(tmp_path, monkeypatch):
"""A fresh box defaults to a model nobody can run; the first provider key
that arrives (by deploy, not just Settings) makes its recommended model
the default — a working default is never stolen."""
monkeypatch.delenv("OPENWORKER_BASE_DIR", raising=False)
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
manager = SessionManager(data_dir=tmp_path / "mgr")
from coworker.secrets import SecretStore
manager.secrets = SecretStore(tmp_path / "secrets.json")
assert manager.get_settings()["model_ready"] is False
# The deploy path writes the profile then calls adopt — same as the joiner.
manager.secrets.put("provider:anthropic", {"api_key": "sk-ant-test"})
adopted = manager.adopt_provider_default("anthropic")
assert adopted and adopted.startswith("anthropic:")
s = manager.get_settings()
assert s["model"] == adopted and s["model_ready"] is True
# A second key does not steal a working default.
manager.secrets.put("provider:openai", {"api_key": "sk-test"})
assert manager.adopt_provider_default("openai") is None
assert manager.get_settings()["model"] == adopted
# -- store_managed_grant_bundle: the ONE staging routine (desktop + box) ------
def test_managed_grant_bundle_handles_every_family(tmp_path):
from coworker.connectors.setup import store_managed_grant_bundle
from coworker.secrets import SecretStore
grant = {"user_id": "usr_1", "machine_credential": "mc_1"}
# Generic (Notion-style, multi-account layer): stamps ride the profile.
s = SecretStore(tmp_path / "a.json")
out = store_managed_grant_bundle(s, "notion", {"provider": "notion", "connector": "notion", "connection_id": "conn_n", "access_token": "tok", "account": "Acme", "account_id": "ws_1"}, grant)
assert out.get("ok"), out
prof = s.get("notion:account:ws_1") or {}
assert prof["access_token"] == "tok" and prof["broker_user_id"] == "usr_1" and prof["machine_credential"] == "mc_1"
assert store_managed_grant_bundle(s, "notion", {"connector": "notion"}, grant)["ok"] is False
# GitHub: one profile per installation + pointer, all stamped, no tokens.
s = SecretStore(tmp_path / "b.json")
import json as _json
out = store_managed_grant_bundle(s, "github", {"connection_id": "conn_g", "installation_id": "1", "account_login": "a", "account_type": "User", "repo_selection": "all", "github_login": "me", "installations": _json.dumps([{"installation_id": "1", "account_login": "a", "account_type": "User", "repo_selection": "all"}, {"installation_id": "2", "account_login": "org", "account_type": "Organization", "repo_selection": "selected"}])}, grant)
assert out.get("ok"), out
for key in ("github:install:1", "github:install:2"):
p = s.get(key) or {}
assert p["connection_id"] == "conn_g" and p["broker_user_id"] == "usr_1" and p["machine_credential"] == "mc_1"
assert "access_token" not in p
assert (s.get("github:default") or {}).get("machine_credential") == "mc_1"
assert store_managed_grant_bundle(s, "github", {"connection_id": "x"}, grant)["ok"] is False
# Slack: per-workspace bot token + pointer, stamped.
s = SecretStore(tmp_path / "c.json")
out = store_managed_grant_bundle(s, "slack", {"connection_id": "conn_s", "access_token": "xoxb-1", "team_id": "T1", "team_domain": "acme", "bot_user_id": "B1", "slack_user_id": "U1", "account": "Acme"}, grant)
assert out.get("ok"), out
p = s.get("slack:team:T1") or {}
assert p.get("bot_token", p.get("access_token")) and p["machine_credential"] == "mc_1" and p["connection_id"] == "conn_s"
assert (s.get("slack:default") or {}).get("broker_user_id") == "usr_1"