4 Commits
Author SHA1 Message Date
zemion 96c48a7f2d refactor(committee): reuse exact Core actor selection contract
Module Package Release / publish-packages (push) Successful in 13s
Release v0.1.22. Coordinated integrity review: GovOPlaN/govoplan-core#298.
2026-09-08 12:19:37 +02:00
zemion 7c2ec4ec17 fix(packaging): expose immutable WebUI Git package for v0.1.21
Module Package Release / publish-packages (push) Successful in 11s
2026-09-08 02:06:08 +02:00
zemion e84fb631f0 Release govoplan-committee v0.1.21: unify interface contracts and documentation 2026-09-08 01:32:27 +02:00
zemion 46ba69fbfe fix(webui): review committee identifier risk
Module Package Release / publish-packages (push) Successful in 12s
2026-08-24 11:36:34 +02:00
8 changed files with 83 additions and 23 deletions
+18
View File
@@ -100,3 +100,21 @@ From the core checkout, labels can be synced once a local `GITEA_TOKEN` is avail
cd /mnt/DATA/git/govoplan-core
/mnt/DATA/git/govoplan/tools/gitea/gitea-sync-labels.py --root /mnt/DATA/git/govoplan-committee --apply
```
## Git-source WebUI package
The repository root exposes `@govoplan/committee-webui` for Git-tagged release
dependencies. It mirrors the owning `webui/package.json` version, public
TypeScript/CSS exports and peer requirements, with entry paths under
`webui/src`. Consumers provide the shared Core/React peers; the facade runs no
development or install scripts. The source archive contains `webui/src`, this
README and any repository license file. Run module development checks from `webui/`; Python
installation remains governed by `pyproject.toml`.
Das Repository stellt `@govoplan/committee-webui` am Wurzelpfad für versionierte
Git-Abhängigkeiten bereit. Version, öffentliche TypeScript-/CSS-Exporte und
Peer-Anforderungen entsprechen `webui/package.json`; die Einstiegspfade liegen
unter `webui/src`. Gemeinsame Core-/React-Peers stellt die einbindende Anwendung
bereit. Die Fassade führt keine Entwicklungs- oder Installationsskripte aus.
Entwicklungsprüfungen bleiben in `webui/`, die Python-Installation weiterhin in
`pyproject.toml` definiert.
+29 -3
View File
@@ -1,8 +1,34 @@
{
"name": "@govoplan/committee",
"version": "0.1.19",
"name": "@govoplan/committee-webui",
"version": "0.1.22",
"private": true,
"description": "GovOPlaN Committee platform module seed.",
"type": "module",
"peerDependencies": {}
"peerDependencies": {
"@govoplan/core-webui": "^0.1.18",
"lucide-react": "^1.23.0",
"react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20",
"react-router": ">=8.3.0 <9"
},
"main": "webui/src/index.ts",
"module": "webui/src/index.ts",
"types": "webui/src/index.ts",
"exports": {
".": {
"types": "./webui/src/index.ts",
"import": "./webui/src/index.ts"
},
"./styles/committee.css": "./webui/src/styles/committee.css"
},
"peerDependenciesMeta": {
"@govoplan/core-webui": {
"optional": true
}
},
"files": [
"webui/src",
"README.md",
"LICENSE"
]
}
+2 -2
View File
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
[project]
name = "govoplan-committee"
version = "0.1.19"
version = "0.1.22"
description = "GovOPlaN committee governance and formal-decision integration module."
readme = "README.md"
requires-python = ">=3.12"
license = { file = "LICENSE" }
authors = [{ name = "GovOPlaN" }]
dependencies = [
"govoplan-core>=0.1.18",
"govoplan-core>=0.1.46",
"govoplan-access>=0.1.18",
]
+16 -1
View File
@@ -59,7 +59,7 @@ from govoplan_core.db.base import Base
MODULE_ID = "committee"
MODULE_NAME = "Committee"
MODULE_VERSION = "0.1.19"
MODULE_VERSION = "0.1.22"
READ_SCOPE = "committee:workspace:read"
WRITE_SCOPE = "committee:workspace:write"
BALLOT_SCOPE = "committee:ballot:finalize"
@@ -554,6 +554,21 @@ manifest = ModuleManifest(
permissions=PERMISSIONS,
role_templates=ROLE_TEMPLATES,
documentation=(
DocumentationTopic(
id="committee.workspace-layout",
title="Committee workspace layout",
summary="Find workspace actions and read consistently arranged content.",
body="Reload and New body share the workspace-wide action bar at the upper right; Reload sits directly before New. Searching and selecting a body, meeting, or agenda item leaves those workspace actions in place. Item editing, ballots, and finalization remain scoped to the selected record. Disabled controls explain missing authority; administrators grant the existing management permissions rather than changing layouts.",
layer="static",
documentation_types=("user", "admin"),
audience=("user", "module_admin", "operator"),
order=5,
translations={"de": {
"title": "Gremien: Aufbau des Arbeitsbereichs",
"summary": "Arbeitsbereichsaktionen finden und einheitlich angeordnete Inhalte lesen.",
"body": "Neu laden und Neues Gremium stehen oben rechts in der gemeinsamen Arbeitsbereichsleiste; Neu laden steht unmittelbar vor Neu. Suche und Auswahl eines Gremiums, einer Sitzung oder eines Tagesordnungspunkts verändern diese Positionen nicht. Bearbeitung, Abstimmungen und Abschluss bleiben dem ausgewählten Datensatz zugeordnet. Deaktivierte Aktionen erklären fehlende Berechtigungen; Administratoren vergeben die bestehenden Verwaltungsrechte, statt das Layout zu ändern.",
}},
),
DocumentationTopic(
id="committee.data-subject-requests",
title="Committee data-subject requests",
+1 -14
View File
@@ -11,6 +11,7 @@ import uuid
from sqlalchemy import func
from sqlalchemy.orm import Session
from govoplan_core.core.principal_helpers import principal_user_first_actor as _principal_actor
from govoplan_core.core.events import (
EventActorRef,
EventObjectRef,
@@ -1001,20 +1002,6 @@ def _principal_tenant(principal: object) -> str:
return tenant_id
def _principal_actor(principal: object) -> str | None:
user = getattr(principal, "user", None)
for value in (
getattr(user, "id", None),
getattr(principal, "account_id", None),
getattr(principal, "identity_id", None),
getattr(principal, "membership_id", None),
):
candidate = str(value or "").strip()
if candidate:
return candidate
return None
def _session(value: object) -> Session:
if not hasattr(value, "query"):
raise InstitutionalContextError(
+15 -1
View File
@@ -12,7 +12,21 @@ from govoplan_committee.backend.manifest import manifest
class CommitteeDocumentationTests(unittest.TestCase):
def test_german_reference_documentation_is_complete(self) -> None:
topics = manifest.documentation
self.assertEqual(3, len(topics))
by_id = {topic.id: topic for topic in topics}
self.assertEqual(len(topics), len(by_id), "Documentation topic IDs must be unique")
self.assertLessEqual(
{
"committee.module-boundary",
"committee.reference.fields-and-consequences",
"committee.data-subject-requests",
"committee.workspace-layout",
},
set(by_id),
)
self.assertLessEqual(
{"user", "admin"},
set(by_id["committee.workspace-layout"].documentation_types),
)
for topic in topics:
translation = topic.translations.get("de", {})
self.assertTrue(translation.get("title"), topic.id)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@govoplan/committee-webui",
"version": "0.1.19",
"version": "0.1.22",
"private": true,
"type": "module",
"main": "src/index.ts",
@@ -237,7 +237,7 @@ export default function CommitteeRecordDialog({
</FormGrid>
{draft.state === "decided" ? (
<FormField label="Formal Decision ID" documentation={COMMITTEE_FIELD_DOCUMENTATION}>
<input value={draft.decisionId} disabled={busy} onChange={(event) => setDraft({ ...draft, decisionId: event.target.value })} />
<input data-help-risk-reviewed="standard" value={draft.decisionId} disabled={busy} onChange={(event) => setDraft({ ...draft, decisionId: event.target.value })} />
</FormField>
) : null}
</>