feat: complete shared platform UI contracts
This commit is contained in:
@@ -222,11 +222,13 @@ DocumentationSourceKind = Literal[
|
||||
"route",
|
||||
"capability",
|
||||
"policy",
|
||||
"release_catalog",
|
||||
"configuration_package",
|
||||
"wiki",
|
||||
"repository",
|
||||
]
|
||||
DocumentationSourceState = Literal["configured", "disabled", "unavailable"]
|
||||
CapabilityStability = Literal["experimental", "stable", "deprecated"]
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
@@ -336,12 +338,25 @@ class DocumentationSourceDefinition:
|
||||
documentation_types: tuple[DocumentationType, ...] = ("admin",)
|
||||
condition: DocumentationCondition = field(default_factory=DocumentationCondition)
|
||||
state: DocumentationSourceState = "configured"
|
||||
state_reason: str | None = None
|
||||
provenance: Mapping[str, Any] = field(default_factory=dict)
|
||||
inspection: Mapping[str, Any] = field(default_factory=dict)
|
||||
link: DocumentationLink | None = None
|
||||
configuration_key: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CapabilityDocumentation:
|
||||
"""Provider-owned capability metadata safe for generic platform consumers."""
|
||||
|
||||
label: str
|
||||
summary: str
|
||||
contract_version: str | None = None
|
||||
stability: CapabilityStability = "stable"
|
||||
documentation_types: tuple[DocumentationType, ...] = ("admin",)
|
||||
audience: tuple[str, ...] = ()
|
||||
|
||||
|
||||
class ResourceAclProvider(Protocol):
|
||||
resource_type: str
|
||||
|
||||
@@ -412,6 +427,7 @@ class ModuleManifest:
|
||||
delete_veto_providers: Mapping[str, Sequence[DeleteVetoProvider]] = field(default_factory=dict)
|
||||
uninstall_guard_providers: tuple[UninstallGuardProvider, ...] = ()
|
||||
capability_factories: Mapping[str, CapabilityFactory] = field(default_factory=dict)
|
||||
capability_documentation: Mapping[str, CapabilityDocumentation] = field(default_factory=dict)
|
||||
search_providers: tuple["SearchProviderRegistration", ...] = ()
|
||||
search_sources: tuple["SearchSourceProviderRegistration", ...] = ()
|
||||
compatibility: ModuleCompatibility = field(default_factory=ModuleCompatibility)
|
||||
|
||||
@@ -614,6 +614,28 @@ def _validate_manifest_shape(manifest: ModuleManifest) -> None:
|
||||
|
||||
|
||||
def _validate_documentation_extensions(manifest: ModuleManifest) -> None:
|
||||
for capability, metadata in manifest.capability_documentation.items():
|
||||
if capability not in manifest.capability_factories:
|
||||
raise RegistryError(
|
||||
f"Module {manifest.id!r} documents capability {capability!r} "
|
||||
"but does not provide it"
|
||||
)
|
||||
if not metadata.label.strip():
|
||||
raise RegistryError(
|
||||
f"Module {manifest.id!r} capability {capability!r} "
|
||||
"documentation must have a label"
|
||||
)
|
||||
if not metadata.summary.strip():
|
||||
raise RegistryError(
|
||||
f"Module {manifest.id!r} capability {capability!r} "
|
||||
"documentation must have a summary"
|
||||
)
|
||||
if metadata.contract_version is not None and not metadata.contract_version.strip():
|
||||
raise RegistryError(
|
||||
f"Module {manifest.id!r} capability {capability!r} "
|
||||
"documentation contract version must not be empty"
|
||||
)
|
||||
|
||||
provider_keys: set[str] = set()
|
||||
for registration in manifest.documentation_configuration_providers:
|
||||
if not registration.keys:
|
||||
|
||||
Reference in New Issue
Block a user