From e55434f406e953a2fa9e881abb8fb6dccbabd812 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Mon, 24 Aug 2026 11:36:30 +0200 Subject: [PATCH] feat(access): document consequential credential controls --- package.json | 2 +- pyproject.toml | 2 +- src/govoplan_access/__init__.py | 2 +- src/govoplan_access/backend/manifest.py | 41 ++++++++++++++++++- webui/package.json | 2 +- webui/src/features/admin/SystemUsersPanel.tsx | 4 +- webui/src/features/admin/UsersPanel.tsx | 14 ++++--- .../sessions/SessionSettingsPanel.tsx | 8 ++++ 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5d825e4..00ffb10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/access-webui", - "version": "0.1.22", + "version": "0.1.23", "private": true, "type": "module", "main": "webui/src/index.ts", diff --git a/pyproject.toml b/pyproject.toml index 6619622..805646d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-access" -version = "0.1.22" +version = "0.1.23" description = "GovOPlaN access platform module with identity, auth, RBAC, and scope primitives." readme = "README.md" requires-python = ">=3.12" diff --git a/src/govoplan_access/__init__.py b/src/govoplan_access/__init__.py index 77af7b4..8da6f11 100644 --- a/src/govoplan_access/__init__.py +++ b/src/govoplan_access/__init__.py @@ -1,3 +1,3 @@ """GovOPlaN access platform module.""" -__version__ = "0.1.22" +__version__ = "0.1.23" diff --git a/src/govoplan_access/backend/manifest.py b/src/govoplan_access/backend/manifest.py index 970c224..2b296bb 100644 --- a/src/govoplan_access/backend/manifest.py +++ b/src/govoplan_access/backend/manifest.py @@ -862,6 +862,44 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = ( ], }, ), + DocumentationTopic( + id="access.reference.authentication-fields", + title="Authentication and password fields", + summary="Understand which credentials are used for interactive sign-in, initial account enrollment, administrative re-authorization, and automation.", + body=( + "The sign-in email identifies the account and the password authenticates only that account. Initial passwords entered by administrators are transmitted only for account creation; leaving the field empty asks the server to generate a one-time temporary password. Requiring a password change prevents that temporary credential from becoming the long-term credential. Current-password prompts re-authorize a sensitive action and never target the selected user's password. The automation API key in local settings is used only when no interactive browser session token is available; it should be a narrowly scoped, revocable key and must not be shared with other users. Generated passwords are not applied until Use password is selected." + ), + layer="always", + documentation_types=("admin", "user"), + audience=("user", "tenant_admin", "access_admin", "operator"), + order=29, + conditions=(DocumentationCondition(required_modules=("access",)),), + links=( + DocumentationLink(label="Sign in", href="/", kind="runtime"), + DocumentationLink(label="Access administration", href="/admin", kind="runtime"), + DocumentationLink(label="Local connection settings", href="/settings", kind="runtime"), + ), + translations={ + "de": { + "title": "Authentifizierungs- und Passwortfelder", + "summary": "Einordnen, welche Zugangsdaten für die interaktive Anmeldung, die erste Kontoeinrichtung, die erneute administrative Autorisierung und Automatisierung verwendet werden.", + "body": ( + "Die Anmelde-E-Mail identifiziert das Konto; das Passwort authentifiziert ausschließlich dieses Konto. Von Administrierenden eingegebene Anfangspasswörter werden nur zur Kontoerstellung übertragen. Bleibt das Feld leer, erzeugt der Server ein einmaliges temporäres Passwort. Die Pflicht zum Passwortwechsel verhindert, dass diese temporäre Zugangsdaten dauerhaft verwendet werden. Die Abfrage des aktuellen Passworts autorisiert eine sensible Aktion erneut und meint niemals das Passwort der ausgewählten Person. Der Automatisierungs-API-Schlüssel in den lokalen Einstellungen wird nur verwendet, wenn kein interaktives Browser-Sitzungstoken verfügbar ist; er sollte eng begrenzt, widerrufbar und nicht mit anderen Personen geteilt sein. Generierte Passwörter werden erst mit „Passwort verwenden“ übernommen." + ), + } + }, + metadata={ + "kind": "reference", + "help_contexts": [ + "access.authentication.email", + "access.authentication.password", + "access.settings.automation-api-key", + "access.admin.system-users.initial-password", + "access.admin.tenant-users.initial-password", + "access.admin.tenant-users.require-password-change", + ], + }, + ), DocumentationTopic( id="access.workflow.grant-user-access", title="Grant a person access", @@ -1531,6 +1569,7 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = ( "access.sessions.action.revoke", "access.sessions.action.revoke-others", "access.admin.user-sessions", + "access.sessions.field.current-password", ], "api_paths": [ "/api/v1/auth/sessions", @@ -1921,7 +1960,7 @@ def _people_search(context: ModuleContext) -> object: manifest = ModuleManifest( id="access", name="Access", - version="0.1.22", + version="0.1.23", optional_dependencies=("identity", "organizations", "tenancy", "idm"), provides_interfaces=( ModuleInterfaceProvider(name=CAPABILITY_ACCESS_PEOPLE_SEARCH, version="0.1.0"), diff --git a/webui/package.json b/webui/package.json index 42dba89..29ae462 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/access-webui", - "version": "0.1.22", + "version": "0.1.23", "private": true, "type": "module", "scripts": { diff --git a/webui/src/features/admin/SystemUsersPanel.tsx b/webui/src/features/admin/SystemUsersPanel.tsx index fae31ee..f1dd9b9 100644 --- a/webui/src/features/admin/SystemUsersPanel.tsx +++ b/webui/src/features/admin/SystemUsersPanel.tsx @@ -239,8 +239,10 @@ export default function SystemUsersPanel({ setDraft({ ...draft, email: event.target.value })} /> setDraft({ ...draft, displayName: event.target.value })} /> {editing === "new" && - + setDraft({ ...draft, email: event.target.value })} /> setDraft({ ...draft, displayName: event.target.value })} /> {editing === "new" && - + - {editing === "new" && setDraft({ ...draft, passwordResetRequired })} />} + {editing === "new" && setDraft({ ...draft, passwordResetRequired })} />} {editing && editing !== "new" && editing.is_last_active_owner &&

i18n:govoplan-access.this_membership_is_the_tenant_s_last_active_oper.072b247f

}
i18n:govoplan-access.groups.ae9629f4 group.is_active).map((group) => ({ id: group.id, label: group.name, description: group.description, disabled: !canManageGroups }))} selected={draft.groupIds} onChange={(groupIds) => setDraft({ ...draft, groupIds })} emptyText="i18n:govoplan-access.no_groups_exist_yet.9cd029f6" />
@@ -320,11 +324,11 @@ export default function UsersPanel({ settings, auth, canCreate, canUpdate, canSu } - !busy && setRevokingSession(null)} className="" footer={<>}> + !busy && setRevokingSession(null)} className="" footer={<>}> {sessionError &&

{sessionError}

}

i18n:govoplan-access.admin_session_revocation_confirmation.5e551020

- - + +
diff --git a/webui/src/features/sessions/SessionSettingsPanel.tsx b/webui/src/features/sessions/SessionSettingsPanel.tsx index 728aaf4..63c6957 100644 --- a/webui/src/features/sessions/SessionSettingsPanel.tsx +++ b/webui/src/features/sessions/SessionSettingsPanel.tsx @@ -132,6 +132,8 @@ export default function SessionSettingsPanel({ id: "revoke", label: "i18n:govoplan-access.revoke_session.5e551007", variant: "danger", + helpContextId: "access.sessions.action.revoke", + helpModuleId: "access", applicable: !row.current, disabled: busy, disabledReason: busy @@ -208,6 +210,8 @@ export default function SessionSettingsPanel({ destructiveActions={