fix(skills): honor profile-scoped readiness secrets
This commit is contained in:
@@ -150,6 +150,31 @@ class TestRequiredEnvironmentVariablesNormalization:
|
||||
assert _is_env_var_persisted("EMPTY_HOST_KEY", {}) is False
|
||||
assert _is_env_var_persisted("FILLED_KEY", {}) is True
|
||||
|
||||
def test_active_profile_secret_scope_satisfies_requirement(self):
|
||||
"""Cron workers must accept a value hydrated from this profile's vault."""
|
||||
from agent import secret_scope
|
||||
from tools.skills_tool import _is_env_var_persisted
|
||||
|
||||
secret_scope.set_multiplex_active(True)
|
||||
token = secret_scope.set_secret_scope({"VAULT_SKILL_API_KEY": "vault-value"})
|
||||
try:
|
||||
assert _is_env_var_persisted("VAULT_SKILL_API_KEY", {}) is True
|
||||
finally:
|
||||
secret_scope.reset_secret_scope(token)
|
||||
secret_scope.set_multiplex_active(False)
|
||||
|
||||
def test_unscoped_multiplex_requirement_does_not_read_process_environment(self, monkeypatch):
|
||||
"""A worker without a profile scope must keep the fail-closed boundary."""
|
||||
from agent import secret_scope
|
||||
from tools.skills_tool import _is_env_var_persisted
|
||||
|
||||
monkeypatch.setenv("OTHER_PROFILE_SKILL_API_KEY", "other-profile-value")
|
||||
secret_scope.set_multiplex_active(True)
|
||||
try:
|
||||
assert _is_env_var_persisted("OTHER_PROFILE_SKILL_API_KEY", {}) is False
|
||||
finally:
|
||||
secret_scope.set_multiplex_active(False)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _get_category_from_path
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
``load_env``) stays there and is read lazily at call time so origin-module patches are honored."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List
|
||||
@@ -126,8 +125,20 @@ def _is_gateway_surface() -> bool:
|
||||
|
||||
|
||||
def _is_env_var_persisted(var_name: str, env_snapshot: Dict[str, str]) -> bool:
|
||||
"""Set (non-empty) in the .env snapshot, else in the process environment."""
|
||||
return bool(env_snapshot[var_name] if var_name in env_snapshot else os.getenv(var_name))
|
||||
"""Return whether a requirement is present in this profile's secret sources.
|
||||
|
||||
The snapshot keeps the existing ``.env`` precedence. A miss must use
|
||||
``get_secret`` rather than reading ``os.environ`` directly so an active
|
||||
multiplex worker can see its hydrated external secrets without seeing a
|
||||
different profile's process environment.
|
||||
"""
|
||||
if var_name in env_snapshot:
|
||||
return bool(env_snapshot[var_name])
|
||||
try:
|
||||
from agent.secret_scope import UnscopedSecretError, get_secret
|
||||
return bool(get_secret(var_name))
|
||||
except UnscopedSecretError:
|
||||
return False
|
||||
|
||||
|
||||
def _build_setup_note(
|
||||
|
||||
Reference in New Issue
Block a user