Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license

This commit is contained in:
2026-09-05 13:26:46 +03:00
commit 03634b1ca3
11340 changed files with 3442369 additions and 0 deletions
View File
+123
View File
@@ -0,0 +1,123 @@
"""Conformance kit for :class:`agent.secret_sources.base.SecretSource`.
Any secret-source backend — bundled or external plugin — can validate
itself against the contract by subclassing :class:`SecretSourceConformance`
and providing a ``source`` fixture (plus optional per-source config
fixtures). Example::
from tests.secret_sources.conformance import SecretSourceConformance
class TestMySourceConformance(SecretSourceConformance):
@pytest.fixture
def source(self):
return MySource()
The checks encode the parts of the contract that break OTHER people
when violated: never raising, never prompting (stdin closed), respecting
disabled config, valid identity attributes, and orchestrator
compatibility.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from agent.secret_sources.base import (
SECRET_SOURCE_API_VERSION,
FetchResult,
SecretSource,
)
from agent.secret_sources.registry import (
_reset_registry_for_tests,
apply_all,
register_source,
)
class SecretSourceConformance:
"""Base class of contract checks; subclass and provide ``source``."""
@pytest.fixture
def source(self) -> SecretSource: # pragma: no cover — must override
raise NotImplementedError("conformance subclasses must provide a source fixture")
@pytest.fixture
def minimal_cfg(self) -> dict:
"""An enabled-but-unconfigured section — the common misconfig case."""
return {"enabled": True}
# -- identity ----------------------------------------------------------
def test_name_is_lowercase_identifier(self, source):
assert source.name, "source.name must be non-empty"
assert source.name == source.name.lower()
assert source.name.replace("_", "").isalnum()
def test_label_present(self, source):
assert source.label, "source.label must be a human-readable name"
def test_shape_valid(self, source):
assert source.shape in ("mapped", "bulk")
def test_api_version_current(self, source):
assert source.api_version == SECRET_SOURCE_API_VERSION
# -- contract behavior --------------------------------------------------
def test_fetch_never_raises_on_malformed_config(self, source, tmp_path):
"""Every degenerate config shape must produce a FetchResult, not a raise."""
for cfg in ({}, {"enabled": True}, {"enabled": True, "env": "not-a-dict"},
{"enabled": True, "cache_ttl_seconds": "bogus"}, None):
result = source.fetch(cfg if isinstance(cfg, dict) else {}, tmp_path)
assert isinstance(result, FetchResult), (
f"fetch() returned {type(result).__name__} for cfg={cfg!r}"
)
def test_fetch_unconfigured_reports_error_not_secrets(self, source, tmp_path,
minimal_cfg, monkeypatch):
"""enabled=true with nothing else set must fail cleanly with a kind."""
result = source.fetch(minimal_cfg, tmp_path)
assert isinstance(result, FetchResult)
if not result.ok:
assert result.error_kind is not None, (
"errors must carry a machine-readable ErrorKind"
)
assert not result.secrets
def test_disabled_by_default(self, source):
assert source.is_enabled({}) is False
assert source.is_enabled({"enabled": False}) is False
def test_timeout_is_positive(self, source, minimal_cfg):
assert source.fetch_timeout_seconds(minimal_cfg) > 0
# Garbage config must not break the timeout accessor either.
assert source.fetch_timeout_seconds({"timeout_seconds": "junk"}) > 0
def test_protected_vars_are_valid_names(self, source, minimal_cfg):
from agent.secret_sources.base import is_valid_env_name
for var in source.protected_env_vars(minimal_cfg):
assert is_valid_env_name(var)
# -- orchestrator compatibility ------------------------------------------
def test_registers_and_applies_via_orchestrator(self, source, tmp_path,
monkeypatch):
"""The source must survive a full apply_all() pass without breaking it."""
_reset_registry_for_tests()
# Prevent the bundled sources from interfering.
monkeypatch.setattr(
"agent.secret_sources.registry._ensure_builtin_sources", lambda: None
)
try:
assert register_source(source), "register_source() rejected the source"
env: dict = {}
report = apply_all(
{source.name: {"enabled": True}}, tmp_path, environ=env
)
names = [sr.name for sr in report.sources]
assert source.name in names
finally:
_reset_registry_for_tests()
@@ -0,0 +1,184 @@
"""Error remediation for secret sources.
Covers the ErrorKind classification of Bitwarden's `invalid_client`
identity reject, the bws stderr summarizer, the per-source
``remediation()`` hook, and the env_loader startup hint printer.
"""
from __future__ import annotations
from pathlib import Path
from unittest import mock
import pytest
from agent.secret_sources import bitwarden as bw
from agent.secret_sources import onepassword as op
from agent.secret_sources.base import ErrorKind, FetchResult, SecretSource
from agent.secret_sources.bitwarden import (
BitwardenSource,
_classify_bws_error,
_summarize_bws_stderr,
)
from agent.secret_sources.onepassword import OnePasswordSource
_BWS_INVALID_CLIENT_DUMP = """\
Error:
0: Received error message from server: [400 Bad Request] {"error":"invalid_client"}
Location:
crates/bws/src/main.rs:108
Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
"""
# ---------------------------------------------------------------------------
# _summarize_bws_stderr
# ---------------------------------------------------------------------------
def test_summarize_strips_rust_report_noise():
summary = _summarize_bws_stderr(_BWS_INVALID_CLIENT_DUMP)
assert "invalid_client" in summary
assert "Location:" not in summary
assert "main.rs" not in summary
assert "Backtrace" not in summary
assert "Error:" not in summary
# ---------------------------------------------------------------------------
# _classify_bws_error — the invalid_client identity reject is an auth failure
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# BitwardenSource.fetch — auth failures get a human explanation
# ---------------------------------------------------------------------------
def test_fetch_auth_failure_gets_friendly_error(monkeypatch, tmp_path):
src = BitwardenSource()
monkeypatch.setenv("BWS_ACCESS_TOKEN", "0.dead")
monkeypatch.setattr(bw, "find_bws", lambda install_if_missing=True: tmp_path / "bws")
def boom(**kwargs):
raise RuntimeError(
'bws exited 1: Received error message from server: '
'[400 Bad Request] {"error":"invalid_client"}'
)
monkeypatch.setattr(bw, "fetch_bitwarden_secrets", boom)
result = src.fetch({"enabled": True, "project_id": "p"}, tmp_path)
assert result.error_kind == ErrorKind.AUTH_FAILED
assert "revoked, expired" in result.error
assert "BWS_ACCESS_TOKEN" in result.error
assert "invalid_client" in result.error # mechanics preserved
# ---------------------------------------------------------------------------
# remediation() hook
# ---------------------------------------------------------------------------
def test_onepassword_auth_remediation_points_at_token_command():
hint = OnePasswordSource().remediation(ErrorKind.AUTH_FAILED, {})
assert "hermes secrets onepassword token" in hint
assert "OP_SERVICE_ACCOUNT_TOKEN" in hint
def test_remediation_never_raises_on_junk_cfg():
for cfg in (None, [], "nope", 42):
assert isinstance(BitwardenSource().remediation(ErrorKind.AUTH_FAILED, cfg), str)
assert isinstance(OnePasswordSource().remediation(ErrorKind.AUTH_FAILED, cfg), str)
# ---------------------------------------------------------------------------
# env_loader startup hint
# ---------------------------------------------------------------------------
def test_env_loader_prints_remediation_hint(tmp_path, monkeypatch, capsys):
from hermes_cli import env_loader
from agent.secret_sources import registry
registry._reset_registry_for_tests()
env_loader.reset_secret_source_cache()
home = tmp_path / ".hermes"
home.mkdir()
(home / "config.yaml").write_text(
"secrets:\n"
" bitwarden:\n"
" enabled: true\n"
" project_id: proj\n"
)
monkeypatch.setenv("BWS_ACCESS_TOKEN", "0.dead")
monkeypatch.setattr(bw, "find_bws", lambda install_if_missing=True: tmp_path / "bws")
def boom(**kwargs):
raise RuntimeError(
'bws exited 1: Received error message from server: '
'[400 Bad Request] {"error":"invalid_client"}'
)
monkeypatch.setattr(bw, "fetch_bitwarden_secrets", boom)
try:
env_loader._apply_external_secret_sources(home)
finally:
registry._reset_registry_for_tests()
env_loader.reset_secret_source_cache()
err = capsys.readouterr().err
assert "rejected the machine-account access token" in err
assert "hermes secrets bitwarden token" in err
def test_remediation_hint_uses_explicit_profile_scope(tmp_path, monkeypatch):
from agent.secret_sources import registry
from hermes_cli import env_loader
class ScopedSource(SecretSource):
name = "scoped_hint"
label = "Scoped hint"
shape = "mapped"
def __init__(self, marker):
self.marker = marker
def fetch(self, cfg, home_path):
return FetchResult()
def remediation(self, kind, cfg):
return self.marker
monkeypatch.setattr(registry, "_ensure_builtin_sources", lambda: None)
registry._reset_registry_for_tests()
home_a = str((tmp_path / "hint-a").resolve())
home_b = str((tmp_path / "hint-b").resolve())
source_a = ScopedSource("profile-a")
source_b = ScopedSource("profile-b")
assert registry.register_source(source_a, scope=home_a)
assert registry.register_source(source_b, scope=home_b)
try:
assert env_loader._remediation_hint(
"scoped_hint", ErrorKind.AUTH_FAILED, {}, scope=home_b
) == "profile-b"
finally:
registry._reset_registry_for_tests()
@@ -0,0 +1,177 @@
"""Orchestrator-level profile secret handling.
Covers the two halves of the profile-clobber bug cluster:
- ``secrets.preserve_existing`` (#58073): named env vars keep their existing
value even against a source with ``override_existing: true``.
- Profile aliasing (#51447): under a named profile, an applied
``FOO_<PROFILE>`` var also hydrates the canonical ``FOO`` so adapters and
plugins that read fixed env names see the profile's value.
Both are implemented ONCE in ``apply_all()`` so every backend — bundled or
plugin — gets them for free.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from agent.secret_sources import registry
from agent.secret_sources.base import ErrorKind, FetchResult, SecretSource
class _FakeBulk(SecretSource):
name = "fakebulk"
label = "Fake Bulk"
shape = "bulk"
def __init__(self, secrets):
self._secrets = secrets
def override_existing(self, cfg):
return bool(cfg.get("override_existing", True))
def fetch(self, cfg, home_path):
res = FetchResult()
res.secrets = dict(self._secrets)
return res
@pytest.fixture(autouse=True)
def _clean_registry():
registry._reset_registry_for_tests()
registry._BUILTINS_LOADED = True # keep real builtins out
yield
registry._reset_registry_for_tests()
def _apply(secrets, cfg_extra=None, home=Path("/tmp/x/.hermes"), env=None):
registry.register_source(_FakeBulk(secrets), replace=True)
cfg = {"fakebulk": {"enabled": True}}
cfg.update(cfg_extra or {})
env = env if env is not None else {}
report = registry.apply_all(cfg, home, environ=env)
return report, env
PROFILE_HOME = Path("/home/u/.hermes/profiles/milla")
# ---------------------------------------------------------------------------
# preserve_existing
# ---------------------------------------------------------------------------
def test_preserve_existing_beats_override():
report, env = _apply(
{"FEISHU_APP_SECRET": "shared", "OPENAI_API_KEY": "fresh"},
cfg_extra={"preserve_existing": ["FEISHU_APP_SECRET"]},
env={"FEISHU_APP_SECRET": "profile-local", "OPENAI_API_KEY": "stale"},
)
assert env["FEISHU_APP_SECRET"] == "profile-local" # preserved
assert env["OPENAI_API_KEY"] == "fresh" # override still works
sr = report.sources[0]
assert "FEISHU_APP_SECRET" in sr.skipped_existing
assert "OPENAI_API_KEY" in sr.applied
def test_preserve_existing_only_guards_set_vars():
"""A preserve-listed var with NO existing value still gets applied."""
_, env = _apply(
{"FEISHU_APP_SECRET": "shared"},
cfg_extra={"preserve_existing": ["FEISHU_APP_SECRET"]},
env={},
)
assert env["FEISHU_APP_SECRET"] == "shared"
# ---------------------------------------------------------------------------
# profile aliasing
# ---------------------------------------------------------------------------
def test_profile_suffixed_var_hydrates_canonical():
report, env = _apply(
{"TELEGRAM_BOT_TOKEN_MILLA": "123:tok"},
home=PROFILE_HOME,
)
assert env["TELEGRAM_BOT_TOKEN_MILLA"] == "123:tok"
assert env["TELEGRAM_BOT_TOKEN"] == "123:tok"
assert "TELEGRAM_BOT_TOKEN" in report.provenance
assert any("applied profile-scoped" in w
for w in report.sources[0].result.warnings)
def test_hyphenated_profile_name_matches_underscore_suffix():
_, env = _apply(
{"SLACK_APP_TOKEN_MY_BOT": "xapp-1"},
home=Path("/home/u/.hermes/profiles/my-bot"),
)
assert env["SLACK_APP_TOKEN"] == "xapp-1"
def test_source_fetch_reads_injected_environment_without_global_mutation(
monkeypatch, tmp_path
):
"""Cold-profile bootstrap values reach sources through the local mapping."""
from agent.secret_sources.base import get_source_environment
class _BootstrapSource(SecretSource):
name = "bootstrap"
shape = "mapped"
def fetch(self, cfg, home_path):
result = FetchResult()
result.secrets = {
"RESOLVED_API_KEY": get_source_environment()["BOOTSTRAP_TOKEN"]
}
return result
registry.register_source(_BootstrapSource())
monkeypatch.delenv("BOOTSTRAP_TOKEN", raising=False)
env = {"BOOTSTRAP_TOKEN": "profile-token"}
_, applied = _apply(
{},
cfg_extra={"bootstrap": {"enabled": True}},
home=tmp_path,
env=env,
)
assert applied["RESOLVED_API_KEY"] == "profile-token"
assert "BOOTSTRAP_TOKEN" not in __import__("os").environ
def test_empty_injected_environment_does_not_fall_back_to_process(monkeypatch, tmp_path):
from agent.secret_sources.base import get_source_environment
class _CanarySource(SecretSource):
name = "canary"
shape = "mapped"
def fetch(self, cfg, home_path):
result = FetchResult()
assert get_source_environment().get("LEAK_CANARY") is None
return result
registry.register_source(_CanarySource())
monkeypatch.setenv("LEAK_CANARY", "global-secret")
registry.apply_all(
{"canary": {"enabled": True}}, tmp_path, environ={}
)
@@ -0,0 +1,363 @@
"""Tests for the secret-source contract + orchestrator.
Covers: registration gating (API version, name/scheme uniqueness, shape),
apply_all precedence (mapped beats bulk, first-wins, override_existing,
protected vars), conflict surfacing, timeout enforcement, provenance,
and Bitwarden's SecretSource adapter — plus the conformance kit run
against the bundled Bitwarden source.
"""
from __future__ import annotations
import sys
import time
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from agent.secret_sources.base import ( # noqa: E402
SECRET_SOURCE_API_VERSION,
ErrorKind,
FetchResult,
SecretSource,
is_valid_env_name,
run_secret_cli,
scrub_ansi,
)
from agent.secret_sources import registry as reg # noqa: E402
from agent.secret_sources.bitwarden import BitwardenSource # noqa: E402
from tests.secret_sources.conformance import SecretSourceConformance # noqa: E402
@pytest.fixture(autouse=True)
def _clean_registry(monkeypatch):
"""Each test starts with an empty registry and no builtin auto-load."""
reg._reset_registry_for_tests()
monkeypatch.setattr(reg, "_ensure_builtin_sources", lambda: None)
yield
reg._reset_registry_for_tests()
def _make_source(
name="dummy",
shape="mapped",
secrets=None,
error=None,
error_kind=None,
scheme=None,
override=False,
protected=(),
api_version=SECRET_SOURCE_API_VERSION,
fetch_fn=None,
):
"""Build a minimal conforming source for orchestrator tests."""
class _Src(SecretSource):
def fetch(self, cfg, home_path):
if fetch_fn is not None:
return fetch_fn(cfg, home_path)
res = FetchResult()
if error:
res.error = error
res.error_kind = error_kind or ErrorKind.INTERNAL
else:
res.secrets = dict(secrets or {})
return res
def override_existing(self, cfg):
return override
def protected_env_vars(self, cfg):
return frozenset(protected)
_Src.name = name
_Src.label = name.title()
_Src.shape = shape
_Src.scheme = scheme
_Src.api_version = api_version
return _Src()
# ---------------------------------------------------------------------------
# Registration gating
# ---------------------------------------------------------------------------
class TestRegistration:
def test_registers_conforming_source(self):
assert reg.register_source(_make_source()) is True
assert reg.get_source("dummy") is not None
def test_rejects_non_secretsource_instance(self):
assert reg.register_source(object()) is False
def test_same_name_is_isolated_by_profile(self, tmp_path):
from hermes_constants import (
reset_hermes_home_override,
set_hermes_home_override,
)
home_a = str((tmp_path / "secrets-a").resolve())
home_b = str((tmp_path / "secrets-b").resolve())
source_a = _make_source(name="profile_secret", secrets={"A": "a"})
source_b = _make_source(name="profile_secret", secrets={"B": "b"})
assert reg.register_source(source_a, scope=home_a)
assert reg.register_source(source_b, scope=home_b)
token = set_hermes_home_override(home_a)
try:
assert reg.get_source("profile_secret") is source_a
explicit_b_env = {}
report = reg.apply_all(
{"profile_secret": {"enabled": True}},
Path(home_b),
environ=explicit_b_env,
)
assert report.sources[0].result.secrets == {"B": "b"}
assert explicit_b_env == {"B": "b"}
finally:
reset_hermes_home_override(token)
token = set_hermes_home_override(home_b)
try:
assert reg.get_source("profile_secret") is source_b
finally:
reset_hermes_home_override(token)
# ---------------------------------------------------------------------------
# apply_all: precedence, conflicts, protection
# ---------------------------------------------------------------------------
class TestApplyAll:
def test_disabled_sources_do_not_run(self, tmp_path):
called = []
def _fetch(cfg, home):
called.append(True)
return FetchResult(secrets={"A": "1"})
reg.register_source(_make_source(fetch_fn=_fetch))
env: dict = {}
report = reg.apply_all({"dummy": {"enabled": False}}, tmp_path, environ=env)
assert not called
assert not report.sources
assert env == {}
def test_applies_secrets_and_records_provenance(self, tmp_path):
reg.register_source(_make_source(secrets={"API_KEY": "v1"}))
env: dict = {}
report = reg.apply_all({"dummy": {"enabled": True}}, tmp_path, environ=env)
assert env["API_KEY"] == "v1"
assert report.provenance["API_KEY"].source == "dummy"
assert report.provenance["API_KEY"].shape == "mapped"
assert report.provenance["API_KEY"].overrode_env is False
def test_failed_source_does_not_block_others(self, tmp_path):
reg.register_source(
_make_source(name="broken", error="boom", error_kind=ErrorKind.NETWORK)
)
reg.register_source(_make_source(name="works", secrets={"K": "v"}))
env: dict = {}
report = reg.apply_all(
{"broken": {"enabled": True}, "works": {"enabled": True}},
tmp_path, environ=env,
)
assert env["K"] == "v"
broken = [s for s in report.sources if s.name == "broken"][0]
assert broken.result.error_kind is ErrorKind.NETWORK
def test_malformed_secrets_cfg_shapes_are_safe(self, tmp_path):
reg.register_source(_make_source(secrets={"K": "v"}))
for cfg in (None, [], "junk", {"dummy": "not-a-dict"}, {"sources": "junk"}):
report = reg.apply_all(cfg, tmp_path, environ={})
assert isinstance(report, reg.ApplyReport)
# ---------------------------------------------------------------------------
# Shared helpers
# ---------------------------------------------------------------------------
class TestHelpers:
def test_is_valid_env_name(self):
assert is_valid_env_name("GOOD_NAME")
assert is_valid_env_name("_LEADING")
assert not is_valid_env_name("")
assert not is_valid_env_name("1BAD")
assert not is_valid_env_name("bad-name")
assert not is_valid_env_name("has space")
def test_run_secret_cli_minimal_env(self):
proc = run_secret_cli(
[sys.executable, "-c",
"import os, json; print(json.dumps(sorted(os.environ)))"],
)
import json
child_env = json.loads(proc.stdout)
# No credential-bearing vars from the parent env leak through.
assert not any(k.endswith(("_API_KEY", "_TOKEN", "_SECRET"))
for k in child_env)
assert "NO_COLOR" in child_env
# ---------------------------------------------------------------------------
# Bitwarden adapter
# ---------------------------------------------------------------------------
class TestBitwardenSource:
def test_fetch_delegates_to_fetch_bitwarden_secrets(self, tmp_path, monkeypatch):
monkeypatch.setenv("BWS_ACCESS_TOKEN", "0.token")
import agent.secret_sources.bitwarden as bw
monkeypatch.setattr(bw, "find_bws", lambda **kw: Path("/fake/bws"))
captured = {}
def _fake_fetch(**kwargs):
captured.update(kwargs)
return {"MY_KEY": "val"}, ["a warning"]
monkeypatch.setattr(bw, "fetch_bitwarden_secrets", _fake_fetch)
result = BitwardenSource().fetch(
{"enabled": True, "project_id": "proj",
"server_url": " https://vault.bitwarden.eu "},
tmp_path,
)
assert result.ok
assert result.secrets == {"MY_KEY": "val"}
assert result.warnings == ["a warning"]
assert captured["project_id"] == "proj"
assert captured["server_url"] == "https://vault.bitwarden.eu"
assert captured["home_path"] == tmp_path
def test_e2e_through_orchestrator(self, tmp_path, monkeypatch):
"""Full path: registry → BitwardenSource → env, with fetch mocked."""
monkeypatch.setenv("BWS_ACCESS_TOKEN", "0.token")
import agent.secret_sources.bitwarden as bw
monkeypatch.setattr(bw, "find_bws", lambda **kw: Path("/fake/bws"))
monkeypatch.setattr(
bw, "fetch_bitwarden_secrets",
lambda **kw: ({"ANTHROPIC_API_KEY": "sk-ant", "BWS_ACCESS_TOKEN": "steal"}, []),
)
reg.register_source(BitwardenSource())
env = {"BWS_ACCESS_TOKEN": "0.token"}
report = reg.apply_all(
{"bitwarden": {"enabled": True, "project_id": "proj"}},
tmp_path, environ=env,
)
assert env["ANTHROPIC_API_KEY"] == "sk-ant"
# The bootstrap token is protected even though BSM carried it.
assert env["BWS_ACCESS_TOKEN"] == "0.token"
assert report.provenance["ANTHROPIC_API_KEY"].source == "bitwarden"
# ---------------------------------------------------------------------------
# Conformance kit applied to the bundled source
# ---------------------------------------------------------------------------
class TestBitwardenConformance(SecretSourceConformance):
@pytest.fixture
def source(self, monkeypatch):
# Never hit the network / auto-install path in conformance runs.
import agent.secret_sources.bitwarden as bw
monkeypatch.setattr(bw, "find_bws", lambda **kw: None)
monkeypatch.delenv("BWS_ACCESS_TOKEN", raising=False)
return BitwardenSource()
# ---------------------------------------------------------------------------
# 1Password adapter
# ---------------------------------------------------------------------------
class TestOnePasswordSource:
def test_mapped_op_beats_bulk_bitwarden_through_orchestrator(
self, tmp_path, monkeypatch
):
"""The headline multi-source scenario: both vaults claim the same var."""
import agent.secret_sources.bitwarden as bw
import agent.secret_sources.onepassword as op
monkeypatch.setenv("BWS_ACCESS_TOKEN", "0.token")
monkeypatch.setattr(bw, "find_bws", lambda **kw: Path("/fake/bws"))
monkeypatch.setattr(
bw, "fetch_bitwarden_secrets",
lambda **kw: ({"SHARED_KEY": "from-bitwarden",
"BW_ONLY": "bw-val"}, []),
)
monkeypatch.setattr(op, "find_op", lambda *_a, **_kw: Path("/fake/op"))
monkeypatch.setattr(
op, "fetch_onepassword_secrets",
lambda **kw: ({"SHARED_KEY": "from-1password"}, []),
)
reg.register_source(bw.BitwardenSource())
reg.register_source(op.OnePasswordSource())
env = {"BWS_ACCESS_TOKEN": "0.token"}
report = reg.apply_all(
{
# bitwarden listed FIRST — mapped 1Password must still win.
"sources": ["bitwarden", "onepassword"],
"bitwarden": {"enabled": True, "project_id": "proj"},
"onepassword": {"enabled": True,
"env": {"SHARED_KEY": "op://V/I/F"}},
},
tmp_path, environ=env,
)
assert env["SHARED_KEY"] == "from-1password"
assert env["BW_ONLY"] == "bw-val"
assert report.provenance["SHARED_KEY"].source == "onepassword"
assert report.provenance["BW_ONLY"].source == "bitwarden"
assert report.conflicts # the shadowed bitwarden claim is surfaced
class TestOnePasswordConformance(SecretSourceConformance):
@pytest.fixture
def source(self, monkeypatch):
import agent.secret_sources.onepassword as op
monkeypatch.setattr(op, "find_op", lambda *_a, **_kw: None)
monkeypatch.delenv("OP_SERVICE_ACCOUNT_TOKEN", raising=False)
return op.OnePasswordSource()