Locks: permission-aware Unlock in the row menu (deferred from #315 L8) #396

Closed
opened 2026-09-02 20:01:03 +00:00 by Cordy · 0 comments
Owner

Deferred from #315 (design point L8, shipped v0.6.106 / PR #393 with a simpler client). Today a locked row always shows Unlock in the menu, for everyone; the server enforces the permission matrix (holder / admin / space owner) and other users get a 403 toast. L8 wanted the menu to be honest up front.

What to build

Client-side permission check. The client needs three facts per locked row, two of which it already has:

  • holder → it.lockOwner (shipped, in the listing);
  • own identity + admin flag → whatever let me = null (index.html ~5895) gets populated with at boot — verify at implementation what fields it carries; if the admin flag is missing from the boot payload, extend that response server-side;
  • space ownership → the viewer's ownership of the current space. Options: (a) expose spaceOwner once per listing response (cheap, spaceOwnerCached already exists server-side), or (b) skip the space-owner case client-side and let those users see the action optimistically. Option (a) is the recommendation — it is one field per listing, not per row.

Menu behaviour.

  • Holder → "Unlock".
  • Admin or space owner (not holder) → "Unlock" with the danger styling used for destructive entries (it is a break-lock) and ideally labelled distinctly, e.g. mBreakLock ("Break lock" / "Sperre aufheben" / "Forcer le déverrouillage" / "Forza sblocco") so nobody breaks a colleague's lock thinking it was their own.
  • Neither → no Unlock entry at all; the chip + tooltip already explain the state.

Non-goals. No server changes to the permission matrix (shipped and tested); no change to the 403 path (kept as the backstop — client checks are advisory).

Tests. Web-side: menu construction for the three identity cases (extend the pure-function tests if openRowMenu logic is extracted far enough, else DOM-level checks in the existing web test harness).

Refs: #315 L8 + close-out comment (deferred list), PR #393, web/static/index.html (openRowMenu, let me), internal/api/listmeta.go / spaceOwnerCached.

Deferred from #315 (design point **L8**, shipped v0.6.106 / PR #393 with a simpler client). Today a locked row always shows **Unlock** in the menu, for everyone; the server enforces the permission matrix (holder / admin / space owner) and other users get a 403 toast. L8 wanted the menu to be honest up front. ## What to build **Client-side permission check.** The client needs three facts per locked row, two of which it already has: - holder → `it.lockOwner` (shipped, in the listing); - own identity + admin flag → whatever `let me = null` (index.html ~5895) gets populated with at boot — verify at implementation what fields it carries; if the admin flag is missing from the boot payload, extend that response server-side; - space ownership → the viewer's ownership of the current space. Options: (a) expose `spaceOwner` once per listing response (cheap, `spaceOwnerCached` already exists server-side), or (b) skip the space-owner case client-side and let those users see the action optimistically. Option (a) is the recommendation — it is one field per listing, not per row. **Menu behaviour.** - Holder → "Unlock". - Admin or space owner (not holder) → "Unlock" with the danger styling used for destructive entries (it is a break-lock) and ideally labelled distinctly, e.g. `mBreakLock` ("Break lock" / "Sperre aufheben" / "Forcer le déverrouillage" / "Forza sblocco") so nobody breaks a colleague's lock thinking it was their own. - Neither → no Unlock entry at all; the chip + tooltip already explain the state. **Non-goals.** No server changes to the permission matrix (shipped and tested); no change to the 403 path (kept as the backstop — client checks are advisory). **Tests.** Web-side: menu construction for the three identity cases (extend the pure-function tests if `openRowMenu` logic is extracted far enough, else DOM-level checks in the existing web test harness). Refs: #315 L8 + close-out comment (deferred list), PR #393, `web/static/index.html` (`openRowMenu`, `let me`), `internal/api/listmeta.go` / `spaceOwnerCached`.
Cordy closed this issue 2026-09-02 20:18:03 +00:00
Sign in to join this conversation.
No labels
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: Cordy/Cairn#396
No description provided.