6e7c9d1395
* feat(sync): add bundled `settings` replica kind for cross-device prefs and credentials Adds a single-row `settings` replica that syncs a whitelist of `SystemSettings` fields across devices via per-field LWW (one entry per dot-namespaced path). Plaintext for theme / highlight colour / TTS configuration; encrypted (AES-GCM under the user's sync passphrase) for kosync / Readwise / Hardcover credentials. Highlights: - Push-side diff against an in-memory snapshot for plaintext paths and a localStorage SHA-256 hash for encrypted paths, so a refresh doesn't re-publish or re-prompt for the passphrase. - Pull-side cipher-fingerprint dedupe + per-row passphrase gate; decryption failures surface as toasts (wrong passphrase / orphan cipher) instead of silent drops. - Auto-recovery for orphaned ciphers: when a row references a saltId no longer in `replica_keys`, clear the local hash and re-encrypt under the current salt on the next save. - Single in-flight `/sync/replica-keys` fetch with a value cache to coalesce the boot-time burst of concurrent unlock callers. * fix(sync): guard settings dot-path helpers against prototype-polluting keys Reject `__proto__`, `constructor`, and `prototype` segments in the settings adapter's `readPath` / `writePath`. Every caller currently passes a constant from `SETTINGS_WHITELIST`, so the guard is purely defensive — but it silences the CodeQL prototype-pollution warning on PR #4094 and keeps the helpers safe if a future call site ever forwards an untrusted path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 lines
567 B
SQL
13 lines
567 B
SQL
-- Migration 011: Extend the replicas.kind allowlist with 'settings'.
|
|
-- Per tenet 8 of the replica-sync plan, scalar settings sync via a
|
|
-- single bundled row keyed by ('settings', 'singleton') instead of N
|
|
-- per-kind adapters. The DB CHECK is belt-and-suspenders;
|
|
-- src/libs/replicaSchemas.ts (KIND_ALLOWLIST) is the actual gate.
|
|
|
|
ALTER TABLE public.replicas
|
|
DROP CONSTRAINT IF EXISTS replicas_kind_allowlist;
|
|
|
|
ALTER TABLE public.replicas
|
|
ADD CONSTRAINT replicas_kind_allowlist
|
|
CHECK (kind IN ('dictionary', 'font', 'texture', 'opds_catalog', 'settings'));
|