From 0c3cd4fb3ad1a32cb7ddb00b0992a53991594b79 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 08:55:56 +0100 Subject: [PATCH] Isolate administration guide session-revocation proof Initialise the real persistent auth stores for the guide lifecycle and prove user removal revokes its session and CSRF token. Clarify that an empty role list clears built-in assignments too; no runtime authority changes. Contract-Neutral: Documentation and test-fixture correction only; session revocation, role assignment and authorization runtime contracts are unchanged. Change-source: pulse-maintainer --- docs/RBAC.md | 2 +- frontend-modern/public/docs/RBAC.md | 2 +- internal/api/admin_docs_test.go | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/RBAC.md b/docs/RBAC.md index 7b0f1d69c5..ca9b5d1ccd 100644 --- a/docs/RBAC.md +++ b/docs/RBAC.md @@ -155,7 +155,7 @@ curl --disable --fail-with-body --header "@$HOME/.config/pulse/api-header" \ JSON ``` -To remove all custom roles from a user, send an empty list: +To clear a user's entire role assignment, including built-in roles, send an empty list: ```bash curl --disable --fail-with-body --header "@$HOME/.config/pulse/api-header" \ diff --git a/frontend-modern/public/docs/RBAC.md b/frontend-modern/public/docs/RBAC.md index 7b0f1d69c5..ca9b5d1ccd 100644 --- a/frontend-modern/public/docs/RBAC.md +++ b/frontend-modern/public/docs/RBAC.md @@ -155,7 +155,7 @@ curl --disable --fail-with-body --header "@$HOME/.config/pulse/api-header" \ JSON ``` -To remove all custom roles from a user, send an empty list: +To clear a user's entire role assignment, including built-in roles, send an empty list: ```bash curl --disable --fail-with-body --header "@$HOME/.config/pulse/api-header" \ diff --git a/internal/api/admin_docs_test.go b/internal/api/admin_docs_test.go index e625e449de..331bf05c2d 100644 --- a/internal/api/admin_docs_test.go +++ b/internal/api/admin_docs_test.go @@ -10,6 +10,7 @@ import ( "regexp" "strings" "testing" + "time" "github.com/rcourtman/pulse-go-rewrite/internal/config" "github.com/rcourtman/pulse-go-rewrite/internal/models" @@ -48,7 +49,14 @@ func adminDocBodies(t *testing.T, name, heading string) [][]byte { } func TestAdminDocsCustomRoleLifecycle(t *testing.T) { - manager, err := auth.NewFileManager(t.TempDir()) + dataPath := t.TempDir() + resetPersistentAuthStoresForTests() + t.Cleanup(resetPersistentAuthStoresForTests) + InitPersistentAuthStores(dataPath) + const fixtureSession = "admin-docs-jane-session-fixture" + GetSessionStore().CreateSession(fixtureSession, time.Hour, "fixture", "127.0.0.1", "jane") + fixtureCSRF := GetCSRFStore().GenerateCSRFToken(fixtureSession) + manager, err := auth.NewFileManager(dataPath) if err != nil { t.Fatal(err) } @@ -106,6 +114,14 @@ func TestAdminDocsCustomRoleLifecycle(t *testing.T) { t.Fatalf("assignment did not persist the complete role list: %+v", assignment) } } + if step.method == http.MethodDelete && step.path == "/api/admin/users/jane" { + if _, exists := manager.GetUserAssignment("jane"); exists { + t.Fatal("user removal retained the role assignment") + } + if GetSessionStore().GetSession(fixtureSession) != nil || GetCSRFStore().ValidateCSRFToken(fixtureSession, fixtureCSRF) { + t.Fatal("user removal retained the session or its CSRF token") + } + } } if _, exists := manager.GetRole("alert-manager"); exists { t.Fatal("custom role deletion did not persist")