feat(release): disclose module permissions in catalog
This commit is contained in:
@@ -217,6 +217,11 @@ requirements. Missing dependency/interface providers and unsupported update
|
||||
windows are surfaced before an operator adds the entry to a plan; installer
|
||||
preflight remains authoritative.
|
||||
|
||||
Catalog entries also carry the permission definitions declared by the tagged
|
||||
module manifest. Admin groups and exposes their scopes before an install or
|
||||
update is planned. This is disclosure only: installing a module does not grant
|
||||
its permissions to an account, role, group, tenant, or service account.
|
||||
|
||||
Package lifecycle and availability are intentionally separate:
|
||||
|
||||
- install, update, and uninstall change the instance-wide package composition;
|
||||
|
||||
@@ -5,7 +5,7 @@ import tomllib
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from govoplan_core.core.modules import ModuleManifest
|
||||
from govoplan_core.core.modules import ModuleManifest, PermissionDefinition
|
||||
from govoplan_core.core.provider_governance import (
|
||||
ExternalProviderDeclaration,
|
||||
ModuleArchitectureDeclaration,
|
||||
@@ -88,6 +88,18 @@ class ReleaseCatalogEntrySynthesisTests(unittest.TestCase):
|
||||
id="example",
|
||||
name="Example",
|
||||
version="1.2.3",
|
||||
permissions=(
|
||||
PermissionDefinition(
|
||||
scope="example:records:read",
|
||||
label="Read records",
|
||||
description="Read example records.",
|
||||
category="Records",
|
||||
level="tenant",
|
||||
module_id="example",
|
||||
resource="records",
|
||||
action="read",
|
||||
),
|
||||
),
|
||||
architecture=architecture,
|
||||
external_providers=(provider,),
|
||||
),
|
||||
@@ -112,6 +124,19 @@ class ReleaseCatalogEntrySynthesisTests(unittest.TestCase):
|
||||
"default_authority_mode"
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
{
|
||||
"scope": "example:records:read",
|
||||
"label": "Read records",
|
||||
"description": "Read example records.",
|
||||
"category": "Records",
|
||||
"level": "tenant",
|
||||
"resource": "records",
|
||||
"action": "read",
|
||||
"deprecated": False,
|
||||
},
|
||||
entry["permissions"][0],
|
||||
)
|
||||
|
||||
def test_selective_update_synthesizes_initial_entries_from_package_manifests(self) -> None:
|
||||
payload: dict[str, object] = {
|
||||
|
||||
@@ -172,6 +172,23 @@ def manifest_catalog_entry(
|
||||
entry["dependencies"] = list(manifest.dependencies)
|
||||
if manifest.optional_dependencies:
|
||||
entry["optional_dependencies"] = list(manifest.optional_dependencies)
|
||||
if manifest.permissions:
|
||||
entry["permissions"] = [
|
||||
{
|
||||
"scope": permission.scope,
|
||||
"label": permission.label,
|
||||
"description": permission.description,
|
||||
"category": permission.category,
|
||||
"level": permission.level,
|
||||
"resource": permission.resource,
|
||||
"action": permission.action,
|
||||
"deprecated": permission.deprecated,
|
||||
}
|
||||
for permission in sorted(
|
||||
manifest.permissions,
|
||||
key=lambda item: item.scope,
|
||||
)
|
||||
]
|
||||
if manifest.architecture is not None:
|
||||
entry["architecture"] = manifest.architecture.to_dict()
|
||||
entry["information_governance"] = manifest.information_governance.to_dict()
|
||||
|
||||
Reference in New Issue
Block a user