Skip to main content

REL-NB-006 — Reject stale concurrent notebook saves

FieldValue
StatusOpen; source-verified
Architecture stateSource-backed persistence contract
SeverityHigh
Affected surfaceMultiple browser contexts and authorized collaborators
Componentssparqd/workspace-file-management-backend, sparqd/oqullus; BFF API forwards writes
Associated issuesworkspace-file-management-backend #18, then oqullus #523

Where the problem appears​

Open one notebook in two isolated contexts, save different edits from the same loaded version, and inspect the final object and history.

Concrete observed case​

The client revision counter is local and not supplied as a server precondition. The BFF forwards an unconditional update, and the file service advances the current object version without checking the version originally loaded.

Expected condition​

Load and save expose one canonical object version. A stale update is rejected before overwrite and offers compare, reload, or save-copy recovery.

Cause and evidence​

The persistence contract lacks an expected version or equivalent conditional write. Local revision tracking only protects against changes during one request.

Why it matters​

Two valid editors can silently overwrite one another. History enables forensic recovery but does not prevent the data-loss event.

Existing controls and workarounds​

Notebook history, diff, and revert can recover an earlier complete object after the overwrite is discovered. Coordinate editing or save a copy when concurrent access is expected.

Alternatives considered​

  1. Recommended: optimistic concurrency with current/expected object version and explicit conflict resolution.
  2. Exclusive edit locks — stronger but creates stale-lock and collaboration problems.
  3. Keep last-write-wins with history — rejected because recovery is delayed and user-driven.

Component involvement​

  • sparqd/workspace-file-management-backend enforces conditional updates and returns conflicts.
  • sparqd/oqullus sends the expected version and presents resolution.
  • BFF API preserves the conditional contract without weakening it.

Reproduction and verification​

Follow NB-S018.

Resolution conditions​

Close when a deterministic two-context test rejects the stale write, preserves both recoverable versions, and the UI offers a safe next action.

Validation and blockers​

Source behavior is confirmed. A disposable two-context deployed test remains pending.