Release v0.1.16
Module Package Release / publish-packages (push) Successful in 15s

This commit is contained in:
2026-08-05 19:51:58 +02:00
parent 794fcf90f8
commit a7ed28f6a3
10 changed files with 41 additions and 18 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/access-webui", "name": "@govoplan/access-webui",
"version": "0.1.15", "version": "0.1.16",
"private": true, "private": true,
"type": "module", "type": "module",
"main": "webui/src/index.ts", "main": "webui/src/index.ts",
@@ -18,7 +18,7 @@
"LICENSE" "LICENSE"
], ],
"peerDependencies": { "peerDependencies": {
"@govoplan/core-webui": "^0.1.15", "@govoplan/core-webui": "^0.1.16",
"lucide-react": "^1.23.0", "lucide-react": "^1.23.0",
"react": ">=19.2.7 <20", "react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20",
+2 -2
View File
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "govoplan-access" name = "govoplan-access"
version = "0.1.15" version = "0.1.16"
description = "GovOPlaN access platform module with identity, auth, RBAC, and scope primitives." description = "GovOPlaN access platform module with identity, auth, RBAC, and scope primitives."
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
license = { file = "LICENSE" } license = { file = "LICENSE" }
authors = [{ name = "GovOPlaN" }] authors = [{ name = "GovOPlaN" }]
dependencies = [ dependencies = [
"govoplan-core>=0.1.15", "govoplan-core>=0.1.16",
"redis>=5,<6", "redis>=5,<6",
"SQLAlchemy>=2,<3", "SQLAlchemy>=2,<3",
] ]
+1 -1
View File
@@ -1,3 +1,3 @@
"""GovOPlaN access platform module.""" """GovOPlaN access platform module."""
__version__ = "0.1.15" __version__ = "0.1.16"
@@ -6,6 +6,7 @@ from typing import Any, Literal
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field
from govoplan_core.api.v1.schemas import DeltaDeletedItem from govoplan_core.api.v1.schemas import DeltaDeletedItem
from govoplan_core.i18n import REFERENCE_LANGUAGE_CODE
from govoplan_core.privacy.schemas import PrivacyRetentionPolicyItem, PrivacyRetentionPolicyPatchItem from govoplan_core.privacy.schemas import PrivacyRetentionPolicyItem, PrivacyRetentionPolicyPatchItem
@@ -41,7 +42,11 @@ class TenantAdminItem(BaseModel):
slug: str = Field(min_length=1, max_length=100) slug: str = Field(min_length=1, max_length=100)
name: str = Field(min_length=1, max_length=255) name: str = Field(min_length=1, max_length=255)
description: str | None = None description: str | None = None
default_locale: str = Field(default="en", min_length=1, max_length=20) default_locale: str = Field(
default=REFERENCE_LANGUAGE_CODE,
min_length=1,
max_length=20,
)
settings: dict[str, Any] = Field(default_factory=dict) settings: dict[str, Any] = Field(default_factory=dict)
allow_custom_groups: bool | None = None allow_custom_groups: bool | None = None
allow_custom_roles: bool | None = None allow_custom_roles: bool | None = None
@@ -81,7 +86,7 @@ class TenantCreateRequest(BaseModel):
name: str name: str
owner_account_id: str | None = None owner_account_id: str | None = None
description: str | None = None description: str | None = None
default_locale: str = "en" default_locale: str = REFERENCE_LANGUAGE_CODE
settings: dict[str, Any] = Field(default_factory=dict) settings: dict[str, Any] = Field(default_factory=dict)
allow_custom_groups: bool | None = None allow_custom_groups: bool | None = None
allow_custom_roles: bool | None = None allow_custom_roles: bool | None = None
@@ -105,7 +110,11 @@ class TenantSettingsItem(BaseModel):
id: str id: str
slug: str slug: str
name: str name: str
default_locale: str = Field(default="en", min_length=1, max_length=20) default_locale: str = Field(
default=REFERENCE_LANGUAGE_CODE,
min_length=1,
max_length=20,
)
available_languages: list[dict[str, Any]] = Field(default_factory=list) available_languages: list[dict[str, Any]] = Field(default_factory=list)
system_enabled_language_codes: list[str] = Field(default_factory=list) system_enabled_language_codes: list[str] = Field(default_factory=list)
enabled_language_codes: list[str] = Field(default_factory=list) enabled_language_codes: list[str] = Field(default_factory=list)
@@ -817,7 +826,7 @@ class ConfigurationPackageExportResponse(BaseModel):
class SystemSettingsItem(BaseModel): class SystemSettingsItem(BaseModel):
default_locale: str = "en" default_locale: str = REFERENCE_LANGUAGE_CODE
allow_tenant_custom_groups: bool = True allow_tenant_custom_groups: bool = True
allow_tenant_custom_roles: bool = True allow_tenant_custom_roles: bool = True
allow_tenant_api_keys: bool = True allow_tenant_api_keys: bool = True
+2 -2
View File
@@ -372,7 +372,7 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
id="access.reference.admin-access-fields", id="access.reference.admin-access-fields",
title="Access administration fields", title="Access administration fields",
summary="The access administration screens show tenant memberships, groups, roles, and API keys. Admin docs map the visible fields to API payloads and permission scopes.", summary="The access administration screens show tenant memberships, groups, roles, and API keys. Admin docs map the visible fields to API payloads and permission scopes.",
body="Users need the visible labels and a short explanation. Admins also need the backing route, API field, permission, and governance note so they can diagnose unavailable actions.", body="Users need the visible labels and a short explanation. Admins also need the backing route, API field, permission, and governance note so they can diagnose unavailable actions. New API-key secrets use the GovOPlaN `gpn_` marker; previously issued keys retain their original value and remain valid until expiry or revocation.",
layer="configured", layer="configured",
documentation_types=("admin", "user"), documentation_types=("admin", "user"),
audience=("tenant_admin", "access_admin", "operator"), audience=("tenant_admin", "access_admin", "operator"),
@@ -761,7 +761,7 @@ def _people_search(context: ModuleContext) -> object:
manifest = ModuleManifest( manifest = ModuleManifest(
id="access", id="access",
name="Access", name="Access",
version="0.1.15", version="0.1.16",
optional_dependencies=("identity", "organizations", "tenancy", "idm"), optional_dependencies=("identity", "organizations", "tenancy", "idm"),
provides_interfaces=( provides_interfaces=(
ModuleInterfaceProvider(name=CAPABILITY_ACCESS_PEOPLE_SEARCH, version="0.1.0"), ModuleInterfaceProvider(name=CAPABILITY_ACCESS_PEOPLE_SEARCH, version="0.1.0"),
@@ -11,6 +11,7 @@ from govoplan_core.security.time import ensure_aware_utc, utc_now
API_KEY_PREFIX_LENGTH = 12 API_KEY_PREFIX_LENGTH = 12
API_KEY_RANDOM_BYTES = 32 API_KEY_RANDOM_BYTES = 32
API_KEY_SECRET_PREFIX = "gpn_"
@dataclass(slots=True) @dataclass(slots=True)
@@ -28,7 +29,7 @@ def verify_api_key(secret: str, expected_hash: str) -> bool:
def generate_api_key_secret() -> str: def generate_api_key_secret() -> str:
return generate_secret("mm_", random_bytes=API_KEY_RANDOM_BYTES) return generate_secret(API_KEY_SECRET_PREFIX, random_bytes=API_KEY_RANDOM_BYTES)
def api_key_prefix(secret: str) -> str: def api_key_prefix(secret: str) -> str:
+14 -1
View File
@@ -5,17 +5,30 @@ import pathlib
import tomllib import tomllib
import unittest import unittest
from govoplan_access.backend.api.v1.admin_schemas import (
SystemSettingsItem,
TenantCreateRequest,
)
ROOT = pathlib.Path(__file__).resolve().parents[1] ROOT = pathlib.Path(__file__).resolve().parents[1]
class OptionalTenancyContractTests(unittest.TestCase): class OptionalTenancyContractTests(unittest.TestCase):
def test_compatibility_admin_schemas_use_german_reference_default(self) -> None:
tenant = TenantCreateRequest(slug="example", name="Example")
self.assertEqual("de", tenant.default_locale)
self.assertEqual("de", SystemSettingsItem().default_locale)
def test_access_package_does_not_require_tenancy_to_install(self) -> None: def test_access_package_does_not_require_tenancy_to_install(self) -> None:
project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))["project"] project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))["project"]
dependencies = tuple(project["dependencies"]) dependencies = tuple(project["dependencies"])
self.assertIn("govoplan-core>=0.1.11", dependencies) self.assertTrue(
any(item.startswith("govoplan-core>=") for item in dependencies)
)
self.assertNotIn("govoplan-tenancy>=0.1.8", dependencies) self.assertNotIn("govoplan-tenancy>=0.1.8", dependencies)
self.assertFalse(any(item.startswith("govoplan-tenancy") for item in dependencies)) self.assertFalse(any(item.startswith("govoplan-tenancy") for item in dependencies))
+1 -1
View File
@@ -225,7 +225,7 @@ class ServiceAccountTests(unittest.TestCase):
expires_at=None, expires_at=None,
) )
self.assertEqual(2, item.revision) self.assertEqual(2, item.revision)
self.assertTrue(first.secret.startswith("mm_")) self.assertTrue(first.secret.startswith("gpn_"))
self.assertNotEqual(first.secret, first.model.key_hash) self.assertNotEqual(first.secret, first.model.key_hash)
item, previous, replacement = rotate_service_account_credential( item, previous, replacement = rotate_service_account_credential(
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/access-webui", "name": "@govoplan/access-webui",
"version": "0.1.15", "version": "0.1.16",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@@ -16,7 +16,7 @@
} }
}, },
"peerDependencies": { "peerDependencies": {
"@govoplan/core-webui": "^0.1.15", "@govoplan/core-webui": "^0.1.16",
"lucide-react": "^1.23.0", "lucide-react": "^1.23.0",
"react": ">=19.2.7 <20", "react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20",
+2 -2
View File
@@ -286,7 +286,7 @@ export const generatedTranslations: PlatformTranslations = {
"i18n:govoplan-access.slug.094da9b9": "Slug", "i18n:govoplan-access.slug.094da9b9": "Slug",
"i18n:govoplan-access.source_module.62b7241c": "Source module", "i18n:govoplan-access.source_module.62b7241c": "Source module",
"i18n:govoplan-access.status.bae7d5be": "Status", "i18n:govoplan-access.status.bae7d5be": "Status",
"i18n:govoplan-access.store_it_in_a_secret_manager_only_its_prefix_and.796ac588": "Store it in a secret manager. Only its prefix and hash remain in Multi Seal Mail.", "i18n:govoplan-access.store_it_in_a_secret_manager_only_its_prefix_and.796ac588": "Store it in a secret manager. GovOPlaN retains only the displayed prefix and a verification hash.",
"i18n:govoplan-access.suspend_tenant.151d283a": "Suspend tenant", "i18n:govoplan-access.suspend_tenant.151d283a": "Suspend tenant",
"i18n:govoplan-access.suspend_value_existing_data_remains_retained_but.19bccd78": "Suspend {value0}? Existing data remains retained, but its members cannot use the tenant.", "i18n:govoplan-access.suspend_value_existing_data_remains_retained_but.19bccd78": "Suspend {value0}? Existing data remains retained, but its members cannot use the tenant.",
"i18n:govoplan-access.suspend_value.03a74b32": "Suspend {value0}", "i18n:govoplan-access.suspend_value.03a74b32": "Suspend {value0}",
@@ -666,7 +666,7 @@ export const generatedTranslations: PlatformTranslations = {
"i18n:govoplan-access.slug.094da9b9": "Slug", "i18n:govoplan-access.slug.094da9b9": "Slug",
"i18n:govoplan-access.source_module.62b7241c": "Quellmodul", "i18n:govoplan-access.source_module.62b7241c": "Quellmodul",
"i18n:govoplan-access.status.bae7d5be": "Status", "i18n:govoplan-access.status.bae7d5be": "Status",
"i18n:govoplan-access.store_it_in_a_secret_manager_only_its_prefix_and.796ac588": "Store it in a secret manager. Only its prefix and hash remain in Multi Seal Mail.", "i18n:govoplan-access.store_it_in_a_secret_manager_only_its_prefix_and.796ac588": "Speichern Sie ihn in einem Secret-Manager. GovOPlaN speichert nur das angezeigte Präfix und einen Prüfhash.",
"i18n:govoplan-access.suspend_tenant.151d283a": "Suspend tenant", "i18n:govoplan-access.suspend_tenant.151d283a": "Suspend tenant",
"i18n:govoplan-access.suspend_value_existing_data_remains_retained_but.19bccd78": "Suspend {value0}? Existing data remains retained, but its members cannot use the tenant.", "i18n:govoplan-access.suspend_value_existing_data_remains_retained_but.19bccd78": "Suspend {value0}? Existing data remains retained, but its members cannot use the tenant.",
"i18n:govoplan-access.suspend_value.03a74b32": "Suspend {value0}", "i18n:govoplan-access.suspend_value.03a74b32": "Suspend {value0}",