feat: expose capability and catalog documentation

This commit is contained in:
2026-07-31 04:21:34 +02:00
parent af18f072d8
commit e2bf104c53
7 changed files with 555 additions and 44 deletions
+109 -3
View File
@@ -10,6 +10,7 @@ from fastapi import HTTPException
from govoplan_access.backend.manifest import get_manifest as get_access_manifest
from govoplan_core.core.modules import DocumentationCondition, DocumentationLink, DocumentationTopic, ModuleManifest, NavItem
from govoplan_core.core.modules import (
CapabilityDocumentation,
DocumentationConfigurationDecision,
DocumentationConfigurationProviderRegistration,
DocumentationSourceDefinition,
@@ -27,7 +28,10 @@ from govoplan_docs.backend.api.v1.routes import (
docs_context,
)
from govoplan_docs.backend.manifest import get_manifest as get_docs_manifest
from govoplan_docs.backend.sources import build_documentation_source_registry
from govoplan_docs.backend.sources import (
_release_catalog_sources,
build_documentation_source_registry,
)
class FakePrincipal:
@@ -446,6 +450,14 @@ class DocsContextTests(unittest.TestCase):
"example.lookup": lambda _context: object(),
"policy.example": lambda _context: object(),
},
capability_documentation={
"example.lookup": CapabilityDocumentation(
label="Example lookup",
summary="Resolves example records through a stable provider contract.",
contract_version="2",
audience=("module_admin",),
),
},
frontend=FrontendModule(
module_id="example",
routes=(
@@ -490,7 +502,10 @@ class DocsContextTests(unittest.TestCase):
),
)
sources = build_documentation_source_registry((manifest,)).sources()
sources = build_documentation_source_registry(
(manifest,),
include_runtime_catalogs=False,
).sources()
self.assertEqual(
{source.item.kind for source in sources},
@@ -505,6 +520,14 @@ class DocsContextTests(unittest.TestCase):
},
)
self.assertNotIn("must-not-leak", repr(sources))
capability_source = next(
source for source in sources
if source.item.kind == "capability"
)
self.assertEqual(capability_source.item.label, "Example lookup")
self.assertEqual(capability_source.item.inspection.summary, "Resolves example records through a stable provider contract.")
self.assertEqual(capability_source.item.inspection.contract_version, "2")
self.assertEqual(capability_source.item.inspection.audience, ["module_admin"])
for source in sources:
self.assertTrue(source.item.id.startswith("example."))
self.assertEqual("example", source.item.owner_module_id)
@@ -513,6 +536,86 @@ class DocsContextTests(unittest.TestCase):
source.item.inspection_url,
)
def test_release_and_configuration_catalogs_become_typed_sources(self) -> None:
release_sources = _release_catalog_sources(
"modules",
"Module release catalog",
{
"configured": True,
"valid": True,
"channel": "stable",
"sequence": 12,
"generated_at": "2026-07-31T10:00:00Z",
"signed": True,
"trusted": True,
"cache_used": False,
"warnings": [],
"modules": [{
"module_id": "files",
"name": "Files",
"version": "0.1.10",
"description": "Managed files.",
"action": "install",
"tags": ["official"],
}],
},
)
self.assertEqual(len(release_sources), 1)
release = release_sources[0].item
self.assertEqual(release.kind, "release_catalog")
self.assertEqual(release.state, "configured")
self.assertEqual(release.inspection.entry_count, 1)
self.assertEqual(release.inspection.entries[0].description, "Managed files.")
configuration_sources = _release_catalog_sources(
"configuration_packages",
"Configuration package catalog",
{
"configured": True,
"valid": True,
"channel": "stable",
"signed": True,
"trusted": True,
"packages": [{
"package_id": "public-service.base",
"name": "Public service base",
"version": "3",
"description": "Baseline configuration for a public service.",
"required_modules": [{"module_id": "access"}],
"required_capabilities": ["policy.retention"],
"tags": ["reference"],
}],
},
)
self.assertEqual(len(configuration_sources), 2)
package = next(
source.item for source in configuration_sources
if source.item.kind == "configuration_package"
)
self.assertEqual(package.inspection.package_id, "public-service.base")
self.assertEqual(package.inspection.required_modules, ["access"])
self.assertEqual(package.inspection.required_capabilities, ["policy.retention"])
def test_docs_manifest_links_repository_and_wiki_sources(self) -> None:
sources = build_documentation_source_registry(
(get_docs_manifest(),),
include_runtime_catalogs=False,
).sources()
source_kinds = {source.item.kind for source in sources}
self.assertIn("repository", source_kinds)
self.assertIn("wiki", source_kinds)
self.assertTrue(any(
source.item.inspection.href.endswith("/govoplan-docs/wiki")
for source in sources
if source.item.kind == "wiki"
))
self.assertTrue(any(
"DOCUMENTATION_LAYER_CONCEPT.md" in source.item.inspection.href
for source in sources
if source.item.kind == "repository"
))
def test_source_visibility_hides_unauthorized_ids(self) -> None:
manifest = ModuleManifest(
id="example",
@@ -536,7 +639,10 @@ class DocsContextTests(unittest.TestCase):
)
registry = PlatformRegistry()
registry.register(manifest)
sources = build_documentation_source_registry((manifest,)).sources()
sources = build_documentation_source_registry(
(manifest,),
include_runtime_catalogs=False,
).sources()
denied = _visible_documentation_sources(
sources,