Viewer role enforcement (server refuses unsigned writes) #62

Closed
opened 2026-09-21 18:06:05 +01:00 by cruelacid · 1 comment
Owner

Part of #37. Depends on #39 (signing-key enrolment) reaching high coverage.

What Relay does

Not shipped. "Advanced permissions — granular read/write controls at folder
level" is Active on their roadmap; their issue #26 has been open since 2025;
enableReaderRole defaults to false and their docs say read-only is
unsupported. Shipping this would put us ahead of them on their own roadmap
item.

The trap that must not be missed

ws-server.ts checks only canAccess on three paths: Push (:661),
PutSnapshot (:713) and DeleteDoc (:737). And putSnapshot
(doc-store.ts:190) runs DELETE FROM doc_updates WHERE doc_name = ? AND seq <= ?.

So a viewer role that gates only writes would let a viewer destroy history.
Gate all three, or do not ship it.

The honest caveat to ship alongside

A viewer still holds the folder content key, so they can read forever and fork
locally. What the signature buys is that the relay refuses their writes, so
their edits never reach anyone else. That is a real boundary and it is
defensible — and docs/sync-limitations.md:555 already says any server-enforced
role is a convenience rather than a cryptographic guarantee. Keep saying it.

The reason the role was removed originally — Obsidian offers no cancellable
file-operation hook — no longer applies: the deletion happens locally, the
server refuses to record it, and nobody else sees it.

Rollout

Per folder, once every member has enrolled a signing key. Not a global switch.

Risk

risk:contract.

Verification

A viewer attempts each of the three paths and is refused on all three. Invert and
confirm each test fails. Then assert the caveat: a viewer can still read.

Part of #37. **Depends on #39 (signing-key enrolment) reaching high coverage.** ## What Relay does **Not shipped.** "Advanced permissions — granular read/write controls at folder level" is Active on their roadmap; their issue #26 has been open since 2025; `enableReaderRole` defaults to `false` and their docs say read-only is unsupported. Shipping this would put us **ahead** of them on their own roadmap item. ## The trap that must not be missed `ws-server.ts` checks only `canAccess` on three paths: `Push` (:661), `PutSnapshot` (:713) and `DeleteDoc` (:737). And `putSnapshot` (`doc-store.ts:190`) runs `DELETE FROM doc_updates WHERE doc_name = ? AND seq <= ?`. **So a viewer role that gates only writes would let a viewer destroy history.** Gate all three, or do not ship it. ## The honest caveat to ship alongside A viewer still holds the folder content key, so they can read forever and fork locally. What the signature buys is that **the relay refuses their writes**, so their edits never reach anyone else. That is a real boundary and it is defensible — and `docs/sync-limitations.md:555` already says any server-enforced role is a convenience rather than a cryptographic guarantee. Keep saying it. The reason the role was removed originally — Obsidian offers no cancellable file-operation hook — **no longer applies**: the deletion happens locally, the server refuses to record it, and nobody else sees it. ## Rollout Per folder, once every member has enrolled a signing key. Not a global switch. ## Risk `risk:contract`. ## Verification A viewer attempts each of the three paths and is refused on all three. Invert and confirm each test fails. Then assert the caveat: a viewer can still read.
Author
Owner

Moved to the Vikunja board as NEC-39: https://projectron.nerchure.com/tasks/39

Moved to the Vikunja board as **NEC-39**: https://projectron.nerchure.com/tasks/39
Sign in to join this conversation.
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
Nectenda/nectenda#62
No description provided.