security(docs): hide runtime provider failures from users
This commit is contained in:
@@ -113,7 +113,7 @@ def docs_context(
|
||||
},
|
||||
"evidence": {
|
||||
"optional_modules": optional_modules,
|
||||
"sources": _evidence_sources(),
|
||||
"sources": _evidence_sources() if documentation_type == "admin" else [],
|
||||
"documentation": documentation_layers["evidence"],
|
||||
},
|
||||
},
|
||||
@@ -356,6 +356,8 @@ def _collect_documentation_topics(
|
||||
try:
|
||||
provided_topics = tuple(provider(context))
|
||||
except Exception as exc:
|
||||
if documentation_type != "admin":
|
||||
continue
|
||||
provided_topics = (
|
||||
DocumentationTopic(
|
||||
id=f"{manifest.id}.runtime-documentation-unavailable",
|
||||
|
||||
@@ -151,6 +151,42 @@ class DocsContextTests(unittest.TestCase):
|
||||
"values": ["*.example.invalid"],
|
||||
})
|
||||
|
||||
def test_runtime_provider_failure_is_diagnostic_only(self) -> None:
|
||||
def failing_provider(_context):
|
||||
raise RuntimeError("sensitive provider detail")
|
||||
|
||||
registry = PlatformRegistry()
|
||||
registry.register(ModuleManifest(
|
||||
id="private-module",
|
||||
name="Private module",
|
||||
version="1.0.0",
|
||||
documentation_providers=(failing_provider,),
|
||||
))
|
||||
principal = FakePrincipal({"docs:documentation:read"})
|
||||
|
||||
user_layers = _classify_documentation(
|
||||
registry,
|
||||
principal,
|
||||
settings=None,
|
||||
session=None,
|
||||
documentation_type="user",
|
||||
locale="en",
|
||||
)
|
||||
admin_layers = _classify_documentation(
|
||||
registry,
|
||||
principal,
|
||||
settings=None,
|
||||
session=None,
|
||||
documentation_type="admin",
|
||||
locale="en",
|
||||
)
|
||||
|
||||
self.assertFalse(any(user_layers.values()))
|
||||
self.assertEqual(
|
||||
[topic["id"] for topic in admin_layers["evidence"]],
|
||||
["private-module.runtime-documentation-unavailable"],
|
||||
)
|
||||
|
||||
def test_docs_default_to_user_and_admin_projection_requires_admin_authority(self) -> None:
|
||||
query_default = signature(docs_context).parameters["documentation_type"].default
|
||||
self.assertEqual(query_default.default, "user")
|
||||
@@ -184,6 +220,7 @@ class DocsContextTests(unittest.TestCase):
|
||||
self.assertNotIn("scope_count", payload["actor"])
|
||||
self.assertEqual(payload["layers"]["configured"]["permissions"], [])
|
||||
self.assertEqual(payload["layers"]["available"]["routes"], [])
|
||||
self.assertEqual(payload["layers"]["evidence"]["sources"], [])
|
||||
|
||||
def test_topic_anchor_is_stable(self) -> None:
|
||||
self.assertEqual(
|
||||
|
||||
Reference in New Issue
Block a user