From a7ed28f6a3cf9e3f5f549db9b0e0785910a8c41a Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Wed, 5 Aug 2026 19:51:58 +0200 Subject: [PATCH] Release v0.1.16 --- package.json | 4 ++-- pyproject.toml | 4 ++-- src/govoplan_access/__init__.py | 2 +- .../backend/api/v1/admin_schemas.py | 17 +++++++++++++---- src/govoplan_access/backend/manifest.py | 4 ++-- .../backend/security/api_keys.py | 3 ++- tests/test_optional_tenancy_contract.py | 15 ++++++++++++++- tests/test_service_accounts.py | 2 +- webui/package.json | 4 ++-- webui/src/i18n/generatedTranslations.ts | 4 ++-- 10 files changed, 41 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index e79a520..caf878f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/access-webui", - "version": "0.1.15", + "version": "0.1.16", "private": true, "type": "module", "main": "webui/src/index.ts", @@ -18,7 +18,7 @@ "LICENSE" ], "peerDependencies": { - "@govoplan/core-webui": "^0.1.15", + "@govoplan/core-webui": "^0.1.16", "lucide-react": "^1.23.0", "react": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20", diff --git a/pyproject.toml b/pyproject.toml index 6b081f6..0df93b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-access" -version = "0.1.15" +version = "0.1.16" description = "GovOPlaN access platform module with identity, auth, RBAC, and scope primitives." readme = "README.md" requires-python = ">=3.12" license = { file = "LICENSE" } authors = [{ name = "GovOPlaN" }] dependencies = [ - "govoplan-core>=0.1.15", + "govoplan-core>=0.1.16", "redis>=5,<6", "SQLAlchemy>=2,<3", ] diff --git a/src/govoplan_access/__init__.py b/src/govoplan_access/__init__.py index fae81e6..9858aec 100644 --- a/src/govoplan_access/__init__.py +++ b/src/govoplan_access/__init__.py @@ -1,3 +1,3 @@ """GovOPlaN access platform module.""" -__version__ = "0.1.15" +__version__ = "0.1.16" diff --git a/src/govoplan_access/backend/api/v1/admin_schemas.py b/src/govoplan_access/backend/api/v1/admin_schemas.py index 316135d..5561bc0 100644 --- a/src/govoplan_access/backend/api/v1/admin_schemas.py +++ b/src/govoplan_access/backend/api/v1/admin_schemas.py @@ -6,6 +6,7 @@ from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field from govoplan_core.api.v1.schemas import DeltaDeletedItem +from govoplan_core.i18n import REFERENCE_LANGUAGE_CODE from govoplan_core.privacy.schemas import PrivacyRetentionPolicyItem, PrivacyRetentionPolicyPatchItem @@ -41,7 +42,11 @@ class TenantAdminItem(BaseModel): slug: str = Field(min_length=1, max_length=100) name: str = Field(min_length=1, max_length=255) 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) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None @@ -81,7 +86,7 @@ class TenantCreateRequest(BaseModel): name: str owner_account_id: 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) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None @@ -105,7 +110,11 @@ class TenantSettingsItem(BaseModel): id: str slug: 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) system_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): - default_locale: str = "en" + default_locale: str = REFERENCE_LANGUAGE_CODE allow_tenant_custom_groups: bool = True allow_tenant_custom_roles: bool = True allow_tenant_api_keys: bool = True diff --git a/src/govoplan_access/backend/manifest.py b/src/govoplan_access/backend/manifest.py index 8e2efc3..854fe05 100644 --- a/src/govoplan_access/backend/manifest.py +++ b/src/govoplan_access/backend/manifest.py @@ -372,7 +372,7 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = ( id="access.reference.admin-access-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.", - 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", documentation_types=("admin", "user"), audience=("tenant_admin", "access_admin", "operator"), @@ -761,7 +761,7 @@ def _people_search(context: ModuleContext) -> object: manifest = ModuleManifest( id="access", name="Access", - version="0.1.15", + version="0.1.16", optional_dependencies=("identity", "organizations", "tenancy", "idm"), provides_interfaces=( ModuleInterfaceProvider(name=CAPABILITY_ACCESS_PEOPLE_SEARCH, version="0.1.0"), diff --git a/src/govoplan_access/backend/security/api_keys.py b/src/govoplan_access/backend/security/api_keys.py index 8b0d68e..e34823f 100644 --- a/src/govoplan_access/backend/security/api_keys.py +++ b/src/govoplan_access/backend/security/api_keys.py @@ -11,6 +11,7 @@ from govoplan_core.security.time import ensure_aware_utc, utc_now API_KEY_PREFIX_LENGTH = 12 API_KEY_RANDOM_BYTES = 32 +API_KEY_SECRET_PREFIX = "gpn_" @dataclass(slots=True) @@ -28,7 +29,7 @@ def verify_api_key(secret: str, expected_hash: str) -> bool: 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: diff --git a/tests/test_optional_tenancy_contract.py b/tests/test_optional_tenancy_contract.py index 955358a..3e1aa56 100644 --- a/tests/test_optional_tenancy_contract.py +++ b/tests/test_optional_tenancy_contract.py @@ -5,17 +5,30 @@ import pathlib import tomllib import unittest +from govoplan_access.backend.api.v1.admin_schemas import ( + SystemSettingsItem, + TenantCreateRequest, +) + ROOT = pathlib.Path(__file__).resolve().parents[1] 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: project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))["project"] 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.assertFalse(any(item.startswith("govoplan-tenancy") for item in dependencies)) diff --git a/tests/test_service_accounts.py b/tests/test_service_accounts.py index 34fea66..7ac5467 100644 --- a/tests/test_service_accounts.py +++ b/tests/test_service_accounts.py @@ -225,7 +225,7 @@ class ServiceAccountTests(unittest.TestCase): expires_at=None, ) 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) item, previous, replacement = rotate_service_account_credential( diff --git a/webui/package.json b/webui/package.json index b5a7eba..e312030 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/access-webui", - "version": "0.1.15", + "version": "0.1.16", "private": true, "type": "module", "scripts": { @@ -16,7 +16,7 @@ } }, "peerDependencies": { - "@govoplan/core-webui": "^0.1.15", + "@govoplan/core-webui": "^0.1.16", "lucide-react": "^1.23.0", "react": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20", diff --git a/webui/src/i18n/generatedTranslations.ts b/webui/src/i18n/generatedTranslations.ts index 304c8e9..81ae966 100644 --- a/webui/src/i18n/generatedTranslations.ts +++ b/webui/src/i18n/generatedTranslations.ts @@ -286,7 +286,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-access.slug.094da9b9": "Slug", "i18n:govoplan-access.source_module.62b7241c": "Source module", "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_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}", @@ -666,7 +666,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-access.slug.094da9b9": "Slug", "i18n:govoplan-access.source_module.62b7241c": "Quellmodul", "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_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}",