feat(enclave): surface configurable enclave icon on the settings page (LC-542) #548

Merged
longjacksonle merged 1 commit from feat/lc542-enclave-icon-settings into main 2026-07-13 16:45:30 +02:00

Context

LC-542 asks to let an enclave owner configure their icon as general admin config (not hard-coded, not Bunyip-specific). Grounding against the real code first:

  • There is no hard-coded Bunyip icon to remove. Every Bunyip reference in the codebase is the SSO login provider (LC-22), not a logo or mascot.
  • The per-enclave icon is already owner-configurable. The switcher rail renders SwitcherEntry.logo_url = the per-enclave branding logo (LC-96/LC-141), uploaded at /enclave/{id}/branding (owner/admin gated), stored in branding.logo_upload_id scope=enclave, served at /enclave/{id}/branding/logo. It falls back to the enclave's initial letter.

So the capability already exists as general admin configuration. The real gap was discoverability: the control lived only behind a "branding" sub-page link on the settings page.

What this PR does

Adds an inline Enclave icon card to the enclave settings page that writes the same per-enclave branding logo, so an owner can set the icon without discovering the branding sub-page. It shows the current icon, or a neutral placeholder glyph when unset (help text notes the rail falls back to the enclave's initial), plus a single upload control matching the app's settings-upload vocabulary.

Backend

  • New owner-gated POST /enclave/{id}/icon (require_manage, 2 MiB body cap like branding).
  • Reuses parse_branding_multipart for size/type validation (PNG/JPG/WebP/GIF, 1 MiB) and preserves every other branding field via resolve-then-upsert, so editing the icon never disturbs colors or login copy (same approach as post_branding for a logo-only edit).
  • Validation error re-renders the full branding editor with the specific inline message; success redirects to settings with a localized toast (enclave-flash-icon-updated).
  • No parallel storage and no Bunyip-specific code. The icon is the same general branding logo already rendered by SwitcherEntry.logo_url.

Acceptance criteria

  • Enclave owners can set/change their enclave icon in configuration (now inline on the settings page).
  • No hard-coded Bunyip-specific icon logic remains (none ever existed).
  • The configured icon renders across surfaces (switcher rail, unchanged).
  • Tests cover setting and rendering a custom enclave icon.

Verification

  • routes_branding.rs: owner upload round-trip (sets the enclave logo, renders the icon on the settings page) + non-manager 403 gate.
  • just check green (standalone + saas + desktop + clippy + fmt); i18n_catalog en/es symmetry; routes_branding 21, routes_enclave 19, routes_enclave_nav 7.
  • UI verified with headless-chrome screenshots of the set and unset card states.

Closes LC-542.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GJbJChgMXj7m1Q8GdnTPyT

## Context LC-542 asks to let an enclave owner configure their icon as general admin config (not hard-coded, not Bunyip-specific). Grounding against the real code first: - **There is no hard-coded Bunyip icon to remove.** Every `Bunyip` reference in the codebase is the SSO login provider (LC-22), not a logo or mascot. - **The per-enclave icon is already owner-configurable.** The switcher rail renders `SwitcherEntry.logo_url` = the per-enclave branding logo (LC-96/LC-141), uploaded at `/enclave/{id}/branding` (owner/admin gated), stored in `branding.logo_upload_id` scope=enclave, served at `/enclave/{id}/branding/logo`. It falls back to the enclave's initial letter. So the capability already exists as general admin configuration. The real gap was **discoverability**: the control lived only behind a "branding" sub-page link on the settings page. ## What this PR does Adds an inline **Enclave icon** card to the enclave settings page that writes the same per-enclave branding logo, so an owner can set the icon without discovering the branding sub-page. It shows the current icon, or a neutral placeholder glyph when unset (help text notes the rail falls back to the enclave's initial), plus a single upload control matching the app's settings-upload vocabulary. ## Backend - New owner-gated `POST /enclave/{id}/icon` (`require_manage`, 2 MiB body cap like branding). - Reuses `parse_branding_multipart` for size/type validation (PNG/JPG/WebP/GIF, 1 MiB) and preserves every other branding field via resolve-then-upsert, so editing the icon never disturbs colors or login copy (same approach as `post_branding` for a logo-only edit). - Validation error re-renders the full branding editor with the specific inline message; success redirects to settings with a localized toast (`enclave-flash-icon-updated`). - No parallel storage and no Bunyip-specific code. The icon is the same general branding logo already rendered by `SwitcherEntry.logo_url`. ## Acceptance criteria - [x] Enclave owners can set/change their enclave icon in configuration (now inline on the settings page). - [x] No hard-coded Bunyip-specific icon logic remains (none ever existed). - [x] The configured icon renders across surfaces (switcher rail, unchanged). - [x] Tests cover setting and rendering a custom enclave icon. ## Verification - `routes_branding.rs`: owner upload round-trip (sets the enclave logo, renders the icon on the settings page) + non-manager 403 gate. - `just check` green (standalone + saas + desktop + clippy + fmt); `i18n_catalog` en/es symmetry; `routes_branding` 21, `routes_enclave` 19, `routes_enclave_nav` 7. - UI verified with headless-chrome screenshots of the set and unset card states. Closes LC-542. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01GJbJChgMXj7m1Q8GdnTPyT
feat(enclave): surface configurable enclave icon on the settings page (LC-542)
All checks were successful
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / Nosey parker (pull_request) Successful in 7s
Create release / Create release from merged PR (pull_request) Has been skipped
check-secrets / Kingfisher (pull_request) Successful in 11s
check-secrets / TruffleHog (pull_request) Successful in 11s
Check / clippy + fmt + tests (pull_request) Successful in 8m34s
9b1b53443c
Yousif proposed letting an enclave owner change the icon; David agreed but stressed Let's Chat must stay general (it sits under the Automation Tools platform), not Bunyip-specific. Grounding against the real code: there is no hard-coded Bunyip icon to remove - every "Bunyip" reference is the SSO login provider - and the per-enclave icon shown on the switcher rail is already owner-configurable through the existing branding-logo system (LC-96/LC-141), stored in branding.logo_upload_id scope=enclave and served at /enclave/{id}/branding/logo. So the feature already exists as general admin config; the real gap is discoverability: that control lived only behind a "branding" sub-page link.

This adds an inline "Enclave icon" card to the enclave settings page that writes the same per-enclave branding logo, so an owner can set the icon without discovering the branding sub-page. It shows the current icon (or a neutral placeholder glyph when unset, with help text noting the rail falls back to the enclave's initial) and a single upload control matching the app's settings-upload vocabulary.

Backend: new owner-gated POST /enclave/{id}/icon (require_manage, 2 MiB body cap like branding) reuses the branding multipart parser for size/type validation and preserves every other branding field, so editing the icon from settings never disturbs colors or login copy - exactly how post_branding handles a logo-only edit. A validation error re-renders the full branding editor with the specific message inline rather than losing it through a redirect code; success redirects back to settings with a localized toast.

No parallel storage or Bunyip-specific code is introduced; the icon is the same general branding logo already rendered by SwitcherEntry.logo_url.

Tests: routes_branding.rs gains an owner upload round-trip (sets the enclave logo and renders the icon on the settings page) and a non-manager 403 gate. Full suite green: just check (standalone + saas + desktop + clippy + fmt), i18n_catalog en/es symmetry, routes_branding 21, routes_enclave 19, routes_enclave_nav 7. UI verified with headless-chrome screenshots of the set and unset card states.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJbJChgMXj7m1Q8GdnTPyT
longjacksonle deleted branch feat/lc542-enclave-icon-settings 2026-07-13 16:45:31 +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!548
No description provided.