Locks: space-owner folder locking behind an instance setting (deferred from #315 L2) #395

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

Deferred from #315 (design point L2, shipped v0.6.106 / PR #393 files-only). L2 ratified files-only locking for users — freezing a subtree is the legal-hold instrument, an operator power — with one agreed extension: an instance setting that lets space OWNERS lock folders inside their own spaces (Nikola: "we could have this be enabled on a per instance setting in the administrator window to also allow space-owners to lock their spaces… needs a proper UI implementation then as well").

Semantics (from the L2 discussion)

  • A folder lock is a write-freeze on the subtree: create/overwrite/delete/rename/copy-onto anywhere under the locked folder is refused for everyone except the lock owner; reads never blocked. This is hold.Affected-style subtree matching, not the file lock's exact-path match.
  • Who may lock a folder: only the owner of the space the folder lives in, and only when the instance setting is on. Personal homes: not applicable (your home is yours already). Space roots themselves lockable? Yes — locking the root freezes the whole space.
  • Unlock: same matrix as file locks (holder, admin) — audited unlock/break-lock.
  • Distinct from holds: still user-space (owner can lift it themselves), still shown as a lock chip, not surfaced in the compliance/holds admin panel.

What to build

Setting. spaceFolderLocks bool (default off) in internal/settings; admin toggle in the dashboard (placement with the other instance-behaviour toggles; can share a "Locks" group with #394's cap row).

Enforcement. Extend internal/storage/filelock: Record gains nothing (a dir lock is just a record whose path is a folder); the guard gains an Affected(p)-style check — walk parents of the target path against the index (in-memory, cheap). Only records flagged/created as folder locks participate in subtree matching, so file-lock behaviour is untouched.

API. POST /api/v1/lock accepts folders when (a) setting on, (b) requester is the owning space's owner (reuse spaceOwnerCached). Otherwise the existing 400 stands.

UI. Row menu Lock/Unlock appears on folders when the feature is on and the viewer owns the space (server still enforces). Locked folders get the chip; children inherit enforcement but should NOT each render a chip (only the locked folder shows it) — listing enrichment stays exact-path.

Tests. Subtree refusal matrix (write/delete/rename/copy under a locked folder, non-owner vs owner), space-owner-only lock creation, setting off = folders rejected, chip only on the locked folder.

Refs: #315 (L2 + folder-scope answer), #394 (settings grouping), internal/storage/hold (Affected pattern), internal/api/spaces.go (owner), PR #393.

Deferred from #315 (design point **L2**, shipped v0.6.106 / PR #393 files-only). L2 ratified files-only locking for users — freezing a subtree is the legal-hold instrument, an operator power — with one agreed extension: **an instance setting that lets space OWNERS lock folders inside their own spaces** (Nikola: "we could have this be enabled on a per instance setting in the administrator window to also allow space-owners to lock their spaces… needs a proper UI implementation then as well"). ## Semantics (from the L2 discussion) - A folder lock is a **write-freeze on the subtree**: create/overwrite/delete/rename/copy-onto anywhere under the locked folder is refused for everyone except the lock owner; reads never blocked. This is `hold.Affected`-style subtree matching, not the file lock's exact-path match. - Who may lock a folder: **only the owner of the space the folder lives in**, and only when the instance setting is on. Personal homes: not applicable (your home is yours already). Space roots themselves lockable? Yes — locking the root freezes the whole space. - Unlock: same matrix as file locks (holder, admin) — audited `unlock`/`break-lock`. - Distinct from holds: still user-space (owner can lift it themselves), still shown as a lock chip, not surfaced in the compliance/holds admin panel. ## What to build **Setting.** `spaceFolderLocks` bool (default off) in `internal/settings`; admin toggle in the dashboard (placement with the other instance-behaviour toggles; can share a "Locks" group with #394's cap row). **Enforcement.** Extend `internal/storage/filelock`: `Record` gains nothing (a dir lock is just a record whose path is a folder); the guard gains an `Affected(p)`-style check — walk parents of the target path against the index (in-memory, cheap). Only records flagged/created as folder locks participate in subtree matching, so file-lock behaviour is untouched. **API.** `POST /api/v1/lock` accepts folders when (a) setting on, (b) requester is the owning space's owner (reuse `spaceOwnerCached`). Otherwise the existing 400 stands. **UI.** Row menu Lock/Unlock appears on folders when the feature is on and the viewer owns the space (server still enforces). Locked folders get the chip; children inherit enforcement but should NOT each render a chip (only the locked folder shows it) — listing enrichment stays exact-path. **Tests.** Subtree refusal matrix (write/delete/rename/copy under a locked folder, non-owner vs owner), space-owner-only lock creation, setting off = folders rejected, chip only on the locked folder. Refs: #315 (L2 + folder-scope answer), #394 (settings grouping), `internal/storage/hold` (`Affected` pattern), `internal/api/spaces.go` (`owner`), PR #393.
Cordy closed this issue 2026-09-02 20:13:12 +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#395
No description provided.