Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

83 lines
2.8 KiB
Python

"""The egress denial-guidance helper must turn machine reason codes into clear,
actionable user messages (what was blocked + how to allow it)."""
from __future__ import annotations
import pytest
from local_deep_research.security.egress.guidance import denial_guidance
@pytest.mark.parametrize(
"reason,target,must_contain",
[
# Scope blocks name the scope AND the setting to change.
(
"scope_mismatch_private_only",
"arxiv",
["Private only", "Egress Scope"],
),
(
"scope_mismatch_public_only",
"library",
["Public only", "Egress Scope"],
),
("strict_not_primary", "wikipedia", ["Strict", "primary"]),
# Inference blocks name the require-local toggle.
("provider_cloud_only", "openai", ["Require local LLM", "openai"]),
("provider_cloud", "openai", ["Require local embeddings"]),
("provider_remote", "ollama", ["local"]),
# Hard rule: metadata cannot be overridden.
("blocked_metadata_ip", None, ["cannot be overridden", "metadata"]),
("elasticsearch_cloud_id_public_egress", None, ["Cloud ID", "hosts"]),
("unknown_egress_scope", None, ["unrecognised", "Egress Scope"]),
],
)
def test_guidance_is_clear_and_actionable(reason, target, must_contain):
msg = denial_guidance(reason, target=target)
assert msg and len(msg) > 20
for needle in must_contain:
assert needle in msg, f"{reason}: expected '{needle}' in: {msg}"
def test_guidance_inserts_target():
msg = denial_guidance("scope_mismatch_private_only", target="arxiv")
assert "arxiv" in msg
def test_non_policy_reasons_get_honest_explanation_not_setting_advice():
# A malformed URL isn't a policy block the user fixes via settings.
msg = denial_guidance("url_malformed")
assert "malformed" in msg
assert "Egress Scope" not in msg
def test_unknown_reason_is_safe_and_nonempty():
msg = denial_guidance("brand_new_code_42", target="X")
assert "X" in msg
assert "brand_new_code_42" in msg # surfaced for support
assert msg # never empty
def test_target_none_falls_back_to_this_action():
msg = denial_guidance("scope_mismatch_private_only") # no target
assert msg.startswith("This action")
assert "Egress Scope" in msg
@pytest.mark.parametrize(
"reason,needle",
[
("no_hostname", "no host"),
("unsupported_scheme", "http/https"),
("dangerous_scheme", "non-web scheme"),
("host_unclassified", "resolved or classified"),
("internal_error", "internal error"),
],
)
def test_all_non_policy_reasons_explain_without_setting_advice(reason, needle):
msg = denial_guidance(reason)
assert needle in msg
# These are parse/format failures, not a policy the user toggles.
assert "Egress Scope" not in msg