docs(access): add credential lifecycle contextual help
Module Package Release / publish-packages (push) Successful in 12s

This commit is contained in:
2026-08-21 21:14:31 +02:00
parent fa0c85e03a
commit 2d1b1e356e
11 changed files with 255 additions and 40 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
"""GovOPlaN access platform module."""
__version__ = "0.1.18"
__version__ = "0.1.19"
+124 -4
View File
@@ -556,8 +556,6 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
"access.admin.tenant-users",
"access.admin.tenant-groups",
"access.admin.tenant-roles",
"access.admin.api-keys",
"access.admin.service-accounts",
],
"route": "/admin",
"screen": "Admin",
@@ -625,6 +623,85 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
],
},
),
DocumentationTopic(
id="access.workflow.manage-api-keys",
title="Create and revoke tenant API keys",
summary="Issue a one-time automation secret for an accountable tenant user, constrain its scope and lifetime, and revoke it when access must stop.",
body=(
"Tenant API keys are non-interactive automation credentials owned by an existing tenant user. Select an owner whose current effective permissions contain every requested scope; authorization continues to intersect the stored key scopes with that owner's current permissions, so removing the owner's access also narrows the key. Set the shortest practical expiry and grant only the scopes the client needs. "
"The secret is displayed once after creation. GovOPlaN then retains only its one-way hash and visible prefix, so administrators cannot display or recover it later. Record the value directly in an approved external secret manager and close the one-time dialog only after custody is confirmed. "
"Revocation is immediate and irreversible for that key: existing clients lose access and must be configured with a newly issued credential. Inspect and audit views expose metadata, scopes, timestamps, and the non-authenticating prefix but never secret material."
),
layer="configured",
documentation_types=("admin", "user"),
audience=("tenant_admin", "access_admin", "operator"),
order=32,
conditions=(
DocumentationCondition(
required_modules=("access",),
any_scopes=(
"access:api_key:read",
"access:api_key:create",
"access:api_key:revoke",
"admin:api_keys:read",
"admin:api_keys:create",
"admin:api_keys:revoke",
),
),
),
links=(
DocumentationLink(label="Tenant API keys", href="/admin?section=tenant-api-keys", kind="runtime"),
DocumentationLink(label="API keys API", href="/api/v1/admin/api-keys", kind="api"),
),
translations={
"de": {
"title": "Mandanten-API-Schlüssel erstellen und widerrufen",
"summary": "Geben Sie ein einmal sichtbares Automatisierungsgeheimnis für eine verantwortliche Person aus, begrenzen Sie Umfang und Laufzeit und widerrufen Sie den Schlüssel, sobald der Zugriff enden muss.",
"body": "Mandanten-API-Schlüssel sind nicht interaktive Automatisierungszugänge einer vorhandenen Person im Mandanten. Wählen Sie eine verantwortliche Person, deren aktuelle wirksame Berechtigungen alle gewünschten Scopes enthalten. Bei jeder Nutzung werden die gespeicherten Schlüssel-Scopes weiterhin mit den aktuellen Berechtigungen dieser Person geschnitten; ein Entzug ihrer Berechtigungen schränkt daher auch den Schlüssel ein. Legen Sie die kürzeste praktikable Laufzeit fest und vergeben Sie nur die Scopes, die der Client tatsächlich benötigt. Das Geheimnis wird nach der Erstellung genau einmal angezeigt. Danach speichert GovOPlaN nur einen Einweg-Hash und das sichtbare, nicht zur Anmeldung geeignete Präfix; eine spätere Anzeige oder Wiederherstellung ist nicht möglich. Übertragen Sie den Wert unmittelbar in einen freigegebenen externen Geheimnismanager und schließen Sie den Einmal-Dialog erst nach bestätigter Verwahrung. Ein Widerruf wirkt sofort und kann für diesen Schlüssel nicht rückgängig gemacht werden: Bestehende Clients verlieren den Zugriff und benötigen einen neu ausgegebenen Zugang. Detail- und Auditansichten zeigen Metadaten, Scopes, Zeitpunkte und das Präfix, aber niemals das Geheimnis.",
}
},
metadata={
"kind": "workflow",
"route": "/admin",
"screen": "Tenant API keys",
"help_contexts": [
"access.admin.api-keys",
"access.api-keys.action.reload",
"access.api-keys.action.create",
"access.api-keys.action.inspect",
"access.api-keys.action.revoke",
"access.api-keys.field.show-revoked",
"access.api-keys.field.name",
"access.api-keys.field.owner",
"access.api-keys.field.expiry",
"access.api-keys.field.scopes",
"access.api-keys.secret",
"access.api-keys.confirm-revoke",
],
"prerequisites": [
"The tenant permits API credentials.",
"The actor may create or revoke API keys and may delegate every selected scope.",
"An approved external secret manager and accountable owner are known.",
],
"steps": [
"Choose the accountable owner and the narrowest required scopes.",
"Set the shortest practical expiry before creating the key.",
"Transfer the one-time secret directly into the approved secret manager.",
"Revoke the key when its client, owner, or purpose is no longer valid.",
],
"outcome": "The automation client has a time-bounded credential whose effective access cannot exceed either its stored scopes or its owner's current permissions.",
"limitations": [
"A one-time secret cannot be displayed or recovered after its creation dialog closes.",
"Changing the owner, expiry, or scopes requires a replacement key.",
"Revocation does not update external clients; operators must install a replacement where needed.",
],
"consequences": [
"Revocation immediately rejects subsequent requests made with the key.",
"Removing permissions from the owner immediately narrows effective key access.",
],
"verification": "Reload the key directory, verify owner, prefix, scopes, expiry, and status, then test the intended client without copying secret material into evidence.",
},
),
DocumentationTopic(
id="access.workflow.manage-reusable-credentials",
title="Manage reusable credentials safely",
@@ -738,9 +815,41 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
DocumentationLink(label="Service accounts API", href="/api/v1/admin/service-accounts", kind="api"),
DocumentationLink(label="Credential lifecycle API", href="/api/v1/admin/service-accounts/{service_account_id}/credentials", kind="api"),
),
translations={
"de": {
"title": "Dienstkonten und ihre Zugangsdaten verwalten",
"summary": "Erstellen Sie nicht interaktive Automatisierungsidentitäten, begrenzen Sie deren aktuellen Berechtigungsrahmen und rotieren Sie einmal sichtbare Zugangsdaten ohne menschliche Anmeldung.",
"body": "Dienstkonten sind mandanteneigene Automatisierungsidentitäten ohne Passwort und ohne interaktive Sitzung. Administrierende legen zuerst den Berechtigungsrahmen des Kontos fest und erstellen danach eine oder mehrere unabhängig widerrufbare Zugangsdaten. Jede Zugangsdaten-Berechtigung muss innerhalb dieses Rahmens liegen. Bei jeder Anfrage wird sie erneut mit dem aktuellen Rahmen geschnitten; eine Verkleinerung des Rahmens oder eine Deaktivierung wirkt deshalb sofort. Das Geheimnis wird nur bei Erstellung oder Rotation einmal angezeigt. GovOPlaN speichert anschließend ausschließlich einen Einweg-Hash und das sichtbare Präfix; das Geheimnis kann weder angezeigt noch wiederhergestellt werden. Eine Rotation erzeugt in einer Transaktion den Ersatz und widerruft die vorherigen Zugangsdaten. Ein Widerruf unterbricht bestehende Clients sofort. Die Deaktivierung stoppt alle Anmeldungen des Dienstkontos, kann aber wieder aufgehoben werden. Das endgültige Stilllegen deaktiviert die zugrunde liegende Identität und widerruft sämtliche aktiven Zugangsdaten. Jede Änderung verwendet die aktuelle Revision des Dienstkontos; bei einem Konflikt muss die Ansicht neu geladen werden, damit keine parallele Änderung überschrieben wird.",
}
},
metadata={
"kind": "workflow",
"help_contexts": ["access.admin.service-accounts"],
"help_contexts": [
"access.admin.service-accounts",
"access.service-accounts.action.reload",
"access.service-accounts.action.create",
"access.service-accounts.action.manage",
"access.service-accounts.action.edit",
"access.service-accounts.action.save",
"access.service-accounts.action.activation",
"access.service-accounts.action.retire",
"access.service-accounts.account-editor",
"access.service-accounts.field.name",
"access.service-accounts.field.description",
"access.service-accounts.field.scope-ceiling",
"access.service-accounts.field.show-revoked",
"access.service-accounts.credential-editor",
"access.service-accounts.action.create-credential",
"access.service-accounts.action.save-credential",
"access.service-accounts.action.rotate-credential",
"access.service-accounts.action.revoke-credential",
"access.service-accounts.field.credential-name",
"access.service-accounts.field.credential-expiry",
"access.service-accounts.field.credential-scopes",
"access.service-accounts.secret",
"access.service-accounts.confirm-revoke-credential",
"access.service-accounts.confirm-retire",
],
"prerequisites": [
"The tenant permits API credentials.",
"You have service-account write permission and may delegate every selected scope.",
@@ -751,6 +860,17 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
"Record the one-time secret in an external secret manager.",
"Rotate credentials before expiry and revoke credentials that are no longer used.",
],
"outcome": "The automation principal remains non-interactive and can authenticate only through an active credential whose grant is within the account's current scope ceiling.",
"limitations": [
"One-time credential secrets cannot be displayed or recovered after the creation dialog closes.",
"Deactivation and a reduced scope ceiling affect clients immediately but do not rewrite their external configuration.",
"Retirement revokes every active credential and requires a new service account for later reuse.",
],
"consequences": [
"Rotation revokes the previous credential in the same transaction that creates its replacement.",
"Credential revocation, account deactivation, and retirement immediately reject affected client requests.",
"A stale revision is rejected so a concurrent administration change is not overwritten.",
],
"verification": "The administration table shows the expected active credential count, last-use timestamp, revision, and audit events without exposing secret material.",
},
),
@@ -1134,7 +1254,7 @@ def _people_search(context: ModuleContext) -> object:
manifest = ModuleManifest(
id="access",
name="Access",
version="0.1.18",
version="0.1.19",
optional_dependencies=("identity", "organizations", "tenancy", "idm"),
provides_interfaces=(
ModuleInterfaceProvider(name=CAPABILITY_ACCESS_PEOPLE_SEARCH, version="0.1.0"),