docs: collaborative editing patterns (subscribe-on-view + lock-on-edit)#1458
Conversation
Adds docs/Patterns/collaborative-editing.md as the canonical pattern
doc that ties together OpenRegister's two existing primitives:
- Push events (or-object-{uuid}) — already documented in
Integrations/OpenRegister.md
- Pessimistic locks — already documented in Features/objects.md
The new page explains why they complement each other (subscribe
without lock = silent overwrites; lock without subscribe = surprise
at save), the end-to-end flow, failure modes, and when NOT to use
the pattern (CRDT editing, bulk imports, read-only views).
Cross-links to the @conduction/nextcloud-vue lib composables that
implement the pattern as defaults (useObjectSubscription,
useObjectLock, CnLockedBanner). The lib spec lives at
nextcloud-vue/openspec/changes/collaborative-editing-defaults/ and
is in flight on the beta branch.
Quality Report — ConductionNL/openregister @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ❌ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ❌ 1/153 denied | |||
| npm | ✅ | ✅ 598/598 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
❌ Denied composer licenses
| Package | Version | License |
|---|---|---|
| dompdf/dompdf | v3.1.5 | LGPL-2.1 |
Quality workflow — 2026-05-10 15:32 UTC
Download the full PDF report from the workflow artifacts.
MWest2020
left a comment
There was a problem hiding this comment.
Review — docs-only, no runtime impact
Heldere doc, prima structuur (failure-modes-tabel en "when NOT to use" callout zijn beide nuttig). Maar ik liep tegen een paar feitelijke onjuistheden / kapotte verwijzingen aan die wél belangrijk zijn — dit is een canonieke pattern-doc, dus de referenties moeten kloppen.
Issues
🔴 Kapotte cross-link (×2): ../Integrations/OpenRegister.md bestaat niet.
De doc verwijst tweemaal naar [OpenRegister Push Events](../Integrations/OpenRegister.md) en eenmaal naar #batch-mode-for-bulk-imports op datzelfde pad. docs/Integrations/ bevat alleen custom-webhooks.md, dolphin.md, huggingface.md, index.md, mistral.md, n8n.md, ollama.md, presidio.md, windmill.md. De realtime/notify_push beschrijving leeft op docs/features/realtime-updates.md — die zou ik linken. De PR-checkbox "All cross-links resolve" is hierdoor niet correct.
🔴 Anchor mismatch: ../Features/objects.md#locking.
In docs/Features/objects.md zijn de relevante koppen ## Object Locking and Versioning (slug #object-locking-and-versioning) en ### Locking Objects (slug #locking-objects). Er is geen kop die naar #locking slugified — die anchor zal niet resolven in Docusaurus.
🔴 Niet-bestaande class: OCA\\OpenRegister\\Listener\\NotifyPushListener.
lib/Listener/ bevat geen NotifyPushListener. Geen enkele PHP-file in de repo bevat een class met die naam. Per openspec/changes/archive/2026-03-21-notificatie-engine/specs/notificatie-engine/spec.md:524: "notify_push integration relies on Nextcloud's native behavior (automatic for apps using INotificationManager); no explicit push integration code exists." — Nextcloud's notify_push onderschept INotificationManager::notify() automatisch, een eigen listener is dus niet nodig en bestaat hier niet. Vervangen door de werkelijke bron (b.v. waar INotificationManager::notify() voor object-events wordt aangeroepen, of de realtime-updates.md doc) — of de hele bullet weglaten als de implementatie nog volgt.
🟡 TTL-disambiguatie.
De doc zegt: "acquires a server-side lock with a short TTL (default 30 minutes, renewed every 10 while the user is active)" en het flow-diagram toont {duration: 1800}. De server-side default is echter 1 uur (lib/Db/ObjectEntity.php:839 — ?int $duration=3600). De 30/10-minuten waarden lijken client/lib-defaults te zijn. Dit graag expliciet maken ("the lib passes duration: 1800 to override the server default of 3600"), anders verwarrend voor backend-lezers.
Kleinere observaties
- Nieuwe directory
docs/Patterns/(hoofdletter P) terwijl er aldocs/features/(lowercase) éndocs/Features/(hoofdletter F) bestaan. Filesystem accepteert het, maar de mixed casing is rommelig en Docusaurus sidebar/routing kan case-gevoelig zijn afhankelijk van plugin-config. Overweegdocs/patterns/voor consistentie metdocs/features/. sidebar_position: 1— als er meer Pattern-docs gaan komen, prima; nu is het de enige in die dir, dus inert.- Het flow-diagram is ASCII; werkt goed in Docusaurus maar onthoud dat de bron
or-object-{uuid}payload-format claim ("UUID-only") feitelijk moet kloppen met watrealtime-updates.mdof de daadwerkelijke listener uitstuurt — verifieer voor je merget.
Verdict
Inhoudelijk een waardevolle doc, maar in de huidige vorm staan er drie verwijzingen in die in een review of door een nieuwe contributor onmiddellijk verwarring opleveren (kapotte link, kapotte anchor, niet-bestaande class). Fix de drie 🔴-items voor merge; de 🟡's zijn nice-to-have.
f86e83f
Summary
New canonical pattern doc at docs/Patterns/collaborative-editing.md tying together OR's two existing primitives:
The page explains why they complement each other (subscribe alone = silent overwrites; lock alone = surprise at save), shows the end-to-end flow, lists failure modes, and notes when NOT to use the pattern (CRDT editing, bulk imports, read-only views).
Cross-links to the @conduction/nextcloud-vue lib that ships the pattern as defaults — `useObjectSubscription`, `useObjectLock`, `CnLockedBanner`. The lib spec is in ConductionNL/nextcloud-vue#192.
Test plan
Related