Skip to content

feat(server): harden app_user.settings updates with atomic database-level merge - #988

Open
dembrane-sam-bot wants to merge 1 commit into
mainfrom
sam/ECHO-933-harden-settings
Open

feat(server): harden app_user.settings updates with atomic database-level merge#988
dembrane-sam-bot wants to merge 1 commit into
mainfrom
sam/ECHO-933-harden-settings

Conversation

@dembrane-sam-bot

Copy link
Copy Markdown
Contributor

What this changes

  • Hardens app_user.settings updates by implementing database row-level locking (SELECT ... FOR UPDATE) in PATCH /v2/me, completely eliminating concurrent read-merge-write race conditions — me.py.
  • Implements a recursive deep_merge helper in Python, ensuring that nested dictionaries within settings are merged rather than wholesale replaced, protecting sibling keys from being clobbered — me.py.
  • Separates Directus-based display_name updates from direct Postgres-based settings updates cleanly — me.py.
  • Adds robust unit/integration tests verifying deep_merge (flat keys, nested structures, type mismatch fallbacks) and update_user_settings_atomic correctness (valid transactions, 404 raised on missing user) — test_me_settings_atomic.py.

Why this is needed

The prior implementation performed a shallow merge in Python ({**existing_settings, **body.settings}) inside the API handler and wrote the full dict back. This suffered from:

  1. Shallow merge limitations: Any writer sending a nested dictionary under a shared parent would replace the entire parent object, silently dropping its other nested siblings.
  2. Read-merge-write race: Concurrent PATCH calls from different tabs or client actions could read the stale state at the same time, merge, and overwrite each other, causing silent clobbering.

This change acquires an atomic transaction lock on the specific row in PostgreSQL, deep-merges recursively, and updates atomically.

Closes: ECHO-933

…evel merge

- Implemented database row-level locking (SELECT ... FOR UPDATE) to prevent read-merge-write race conditions.
- Implemented deep_merge in Python to prevent nested dictionary sibling replacement/clobbering.
- Separated Directus display_name updates from direct Postgres settings updates cleanly.
- Added robust unit and integration tests covering deep merge recursively and transaction lock correctness under concurrency.

Closes ECHO-933
@linear

linear Bot commented Aug 10, 2026

Copy link
Copy Markdown

ECHO-933

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant