fix(sidebar): keep enclave context when re-rendering after a category mutation (LC-415) #430

Merged
longjacksonle merged 1 commit from fix/sidebar-category-create-enclave-context into main 2026-06-21 21:05:56 +02:00

Problem

Creating a sidebar room-category did nothing in the browser (LC-415): typing a name and clicking "+ Add category" committed the row to room_categories (visible in the admin panel) but it never appeared in the sidebar.

Root cause

The category mutation handlers re-rendered the whole-sidebar OOB fragment by re-deriving the current enclave from the HX-Current-URL header (current_enclave_from_headers). That parser only understands /enclave/{id} and /room/{id} URLs and returns None otherwise, or when the header is absent / stripped by a proxy / a WebSocket sidebar swap raced the submit. A None re-render collapses load_sidebar to its DM-only shape, which has no categories and no add-category form, so the new category and the input both vanished from the swapped-in sidebar.

The handlers already hold the authoritative enclave id in their own path, so the header round-trip was unnecessary and fragile.

Fix

Split render_sidebar_fragment into the header-driven entry point (still used by the enclave-less read-all / mark-room-read routes) and render_sidebar_with_enclave(state, user, Option<i64>). The seven enclave-scoped category mutations plus the per-user collapse handler now pass their authoritative path enclave_id (collapse derives it from the category). Dropped the now-unused HeaderMap extractors from those handlers.

Test

routes_sidebar_categories::create_response_includes_category_without_hx_header posts a create with no HX-Current-URL header and asserts the rendered fragment contains both the new category name and the enclave-scoped add-category form. Fails before the fix, passes after. just check, just test, just test-saas all green.

Closes LC-415.

🤖 Generated with Claude Code

## Problem Creating a sidebar room-category did nothing in the browser (LC-415): typing a name and clicking "+ Add category" committed the row to `room_categories` (visible in the admin panel) but it never appeared in the sidebar. ## Root cause The category mutation handlers re-rendered the whole-sidebar OOB fragment by re-deriving the current enclave from the `HX-Current-URL` header (`current_enclave_from_headers`). That parser only understands `/enclave/{id}` and `/room/{id}` URLs and returns `None` otherwise, or when the header is absent / stripped by a proxy / a WebSocket sidebar swap raced the submit. A `None` re-render collapses `load_sidebar` to its DM-only shape, which has no categories and no add-category form, so the new category and the input both vanished from the swapped-in sidebar. The handlers already hold the authoritative enclave id in their own path, so the header round-trip was unnecessary and fragile. ## Fix Split `render_sidebar_fragment` into the header-driven entry point (still used by the enclave-less `read-all` / `mark-room-read` routes) and `render_sidebar_with_enclave(state, user, Option<i64>)`. The seven enclave-scoped category mutations plus the per-user collapse handler now pass their authoritative path `enclave_id` (collapse derives it from the category). Dropped the now-unused `HeaderMap` extractors from those handlers. ## Test `routes_sidebar_categories::create_response_includes_category_without_hx_header` posts a create with no `HX-Current-URL` header and asserts the rendered fragment contains both the new category name and the enclave-scoped add-category form. Fails before the fix, passes after. `just check`, `just test`, `just test-saas` all green. Closes LC-415. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(sidebar): keep enclave context when re-rendering after a category mutation (LC-415)
All checks were successful
check-secrets / Nosey parker (push) Successful in 6s
check-secrets / TruffleHog (push) Successful in 8s
check-secrets / Kingfisher (push) Successful in 9s
check-secrets / Nosey parker (pull_request) Successful in 6s
check-secrets / Kingfisher (pull_request) Successful in 10s
check-secrets / TruffleHog (pull_request) Successful in 11s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 8m23s
67541ffb4a
Creating a sidebar room-category did nothing in the browser: the row was committed to `room_categories` (visible in the admin panel) but never appeared in the sidebar. The category mutation handlers re-rendered the whole-sidebar OOB fragment by re-deriving the current enclave from the `HX-Current-URL` header via `current_enclave_from_headers`, which only understands `/enclave/{id}` and `/room/{id}` URLs and returns `None` otherwise (or when the header is absent / stripped by a proxy / a WS sidebar swap raced the submit). A `None` re-render collapses `load_sidebar` to its DM-only shape, which carries no categories and no add-category form, so the new category and the input both vanished from the swapped-in sidebar.

The handlers already hold the authoritative enclave id in their own path, so the header round-trip was both unnecessary and fragile. Split `render_sidebar_fragment` into the header-driven entry point (still used by the enclave-less read-all / mark-room-read routes) and `render_sidebar_with_enclave`, and point the seven enclave-scoped category mutations plus the per-user collapse handler at their path `enclave_id` (collapse derives it from the category). Dropped the now-unused `HeaderMap` extractors from those handlers.

Regression test `create_response_includes_category_without_hx_header` posts a create with no `HX-Current-URL` header and asserts the rendered fragment contains both the new category and the enclave-scoped add-category form; it fails before the fix and passes after. `just check`, `just test`, `just test-saas` all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch fix/sidebar-category-create-enclave-context 2026-06-21 21:05:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!430
No description provided.