feat(access): add governed session management

This commit is contained in:
2026-08-19 22:50:15 +02:00
parent 38fc22c06b
commit 2be1dbc132
16 changed files with 1302 additions and 10 deletions
+73
View File
@@ -84,6 +84,7 @@ ACCESS_PERMISSIONS: tuple[PermissionDefinition, ...] = (
_permission("access:membership:read", "View memberships", "List tenant memberships and effective access.", "Tenant access", "tenant"),
_permission("access:membership:create", "Create memberships", "Create tenant-local account memberships.", "Tenant access", "tenant"),
_permission("access:membership:update", "Update memberships", "Update or suspend tenant memberships.", "Tenant access", "tenant"),
_permission("access:session:manage_own", "Manage own sessions", "Inspect and revoke the current account's browser sessions without exposing credentials.", "Tenant access", "tenant"),
_permission("access:group:read", "View groups", "List tenant groups and members.", "Tenant access", "tenant"),
_permission("access:group:write", "Manage groups", "Create and update tenant groups.", "Tenant access", "tenant"),
_permission("access:group:manage_members", "Manage group members", "Add and remove memberships from groups.", "Tenant access", "tenant"),
@@ -176,6 +177,16 @@ ACCESS_ROLE_TEMPLATES: tuple[RoleTemplate, ...] = (
managed=False,
protected=False,
),
RoleTemplate(
slug="account_security",
name="Account security",
description="Authenticated baseline for inspecting and revoking the current account's browser sessions.",
permissions=("access:session:manage_own",),
level="tenant",
managed=True,
protected=True,
default_authenticated=True,
),
RoleTemplate(
slug="owner",
name="Tenant owner",
@@ -628,6 +639,67 @@ ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
"verification": "The administration table shows the expected active credential count, last-use timestamp, revision, and audit events without exposing secret material.",
},
),
DocumentationTopic(
id="access.workflow.manage-sessions",
title="Review and revoke account sessions",
summary="Inspect active browser sessions and revoke one or every other session without exposing credentials or network identifiers.",
body=(
"Settings > Sessions and devices marks the current browser session and shows only bounded client metadata plus creation, last-seen, and expiry times. "
"Users can revoke another session or all other active sessions; the command session is protected and normal logout remains the way to end it. Revocation is idempotent and takes effect on the next authenticated request. "
"Tenant administrators can inspect only sessions belonging to a membership in their governed tenant. Administrative revocation requires central membership-update permission and current-password re-authorization from an interactive session. "
"Audit evidence records stable actors, targets, and counts without tokens, hashes, cookies, IP addresses, or client strings."
),
layer="always",
documentation_types=("admin", "user"),
audience=("user", "tenant_admin", "access_admin", "operator"),
conditions=(
DocumentationCondition(
required_modules=("access",),
any_scopes=("access:session:manage_own",),
),
),
links=(
DocumentationLink(label="Sessions and devices", href="/settings?section=sessions", kind="runtime"),
DocumentationLink(label="Own sessions API", href="/api/v1/auth/sessions", kind="api"),
DocumentationLink(label="Session management reference", href="docs/SESSION_MANAGEMENT.md", kind="repository"),
),
translations={
"de": {
"title": "Kontositzungen prüfen und widerrufen",
"summary": "Aktive Browsersitzungen prüfen und einzelne oder alle anderen Sitzungen widerrufen, ohne Zugangsdaten oder Netzwerkkennungen offenzulegen.",
"body": (
"Einstellungen > Sitzungen und Geräte kennzeichnet die aktuelle Browsersitzung und zeigt nur begrenzte Clientmetadaten sowie Erstellungs-, Aktivitäts- und Ablaufzeitpunkte. "
"Benutzende können eine andere oder alle anderen aktiven Sitzungen widerrufen; die ausführende Sitzung bleibt geschützt und wird regulär abgemeldet. Der Widerruf ist idempotent und gilt beim nächsten authentifizierten Aufruf. "
"Mandantenadministrierende sehen nur Sitzungen einer Mitgliedschaft im verwalteten Mandanten. Der administrative Widerruf erfordert die zentrale Berechtigung zur Mitgliedschaftsänderung und eine erneute Passwortbestätigung in einer interaktiven Sitzung. "
"Auditnachweise speichern stabile Akteure, Ziele und Anzahlen, aber keine Token, Hashes, Cookies, IP-Adressen oder Clienttexte."
),
}
},
metadata={
"kind": "workflow",
"help_contexts": [
"access.settings.sessions",
"access.sessions.action.revoke",
"access.sessions.action.revoke-others",
"access.admin.user-sessions",
],
"api_paths": [
"/api/v1/auth/sessions",
"/api/v1/auth/sessions/{session_id}/revoke",
"/api/v1/auth/sessions/revoke-others",
"/api/v1/admin/users/{user_id}/sessions",
"/api/v1/admin/users/{user_id}/sessions/{session_id}/revoke",
],
"sensitive_fields_never_returned": [
"token",
"token_hash",
"csrf_token_hash",
"cookie",
"ip_address",
],
},
order=33,
),
DocumentationTopic(
id="access.reference.external-function-role-mappings",
title="Organization function facts and access roles",
@@ -992,6 +1064,7 @@ manifest = ModuleManifest(
ViewSurface(id="access.admin.group-credentials", module_id="access", kind="section", label="Group credentials", order=30),
ViewSurface(id="access.admin.user-credentials", module_id="access", kind="section", label="User credentials", order=30),
ViewSurface(id="access.settings.credentials", module_id="access", kind="section", label="Personal credentials", order=30),
ViewSurface(id="access.settings.sessions", module_id="access", kind="section", label="Sessions and devices", order=20),
),
),
capability_factories={