Skip to content

security(core/R-15): renderer-neutral encrypted desktop storage, durable migration & identity binding #445

Description

@qnbs

Purpose

Implement R-15 as the renderer-neutral encrypted-storage authority for native desktop. This is a Core/security migration requirement, not a Tauri-specific enhancement and not work that should be discarded when Qt replaces Tauri.

The current product truth remains explicit: authoritative Tauri filesystem project data is not yet protected at rest by this future Core design. No UI, release note, or documentation may imply otherwise until the protected path is authoritative and packaged evidence exists.

Architecture boundary

Tauri today ─┐
             ├── typed DesktopPlatform / native contracts ── Rust Core secure storage
Qt target ───┘

Requirements:

  • Rust Core owns encryption/storage semantics.
  • Renderers consume typed operations; they do not own keys, migration state, record identity, or durable-write policy.
  • QML/React must not become a second crypto/storage authority.
  • Direct renderer-specific implementations do not satisfy R-15.
  • Existing Tauri behavior must remain truthful and fail safe during the transition.

Required protected-data inventory

Before implementation, enumerate every native desktop record class and classify it as PROTECTED, NON-SENSITIVE, DERIVED/REGENERABLE, or OUT-OF-SCOPE with rationale. At minimum inspect:

  • project/manuscript data;
  • snapshots/backups/recovery data;
  • settings that contain sensitive values;
  • provider/API credentials;
  • images/assets and metadata;
  • Codex/RAG/vector/index payloads;
  • task/recovery/migration metadata;
  • temporary/staging files created by save, import/export, migration, or recovery.

The inventory is part of the security contract: no protected class may silently fall back to plaintext because a renderer or migration path was overlooked.

Required envelope/key properties

The admitted design must define and test:

  • authenticated encryption;
  • versioned envelope/algorithm metadata;
  • key identity/epoch and rotation semantics;
  • renderer-neutral key lifecycle;
  • explicit locked/unlocked/readability states;
  • logical-record identity binding (AAD or equivalent);
  • corruption/tamper/wrong-key behavior;
  • compatibility/version negotiation;
  • key-loss and factory-reset behavior;
  • backup/recovery interaction;
  • no avoidable plaintext temporary leakage;
  • deterministic redaction/logging policy.

Durability — incorporates #357

A successful protected write must have a documented crash-durability contract, not merely atomic rename semantics. Define platform-appropriate behavior for:

  1. create/write temporary file;
  2. flush/sync file contents as required;
  3. atomic replacement/rename;
  4. persist directory metadata where the platform/filesystem contract requires it;
  5. report failures without claiming durability that has not been reached;
  6. recover safely from orphan temporary/staging files.

The implementation belongs in renderer-neutral/native Core infrastructure wherever practical; do not create a new Tauri-only durable-write authority simply because #357 was originally reported against the Tauri path.

Crash-resumable rekey — incorporates #359

Rotation, enable/disable transitions, and migration from plaintext/legacy envelopes must be resumable and idempotent.

Persist enough journal/checkpoint state to identify:

  • migration operation/version;
  • source and target key epochs;
  • deterministic protected-record inventory;
  • per-record pending/in-progress/done state or equivalent resumable cursor;
  • commit/finalization phase;
  • recovery-required state;
  • safe resume/rollback rules.

Crash/power-loss at every meaningful phase must not silently strand a mixed-key dataset.

Migration admission — incorporates #360

Reads/writes and migration must participate in one coherent admission model.

Required invariants:

  • ordinary protected writes cannot race an exclusive rekey/migration into an obsolete epoch;
  • reads never bypass locked/migrating policy merely because a legacy record is still plaintext;
  • migration owns the required exclusive admission for its critical phases;
  • cancellation/shutdown semantics are explicit;
  • concurrent saves/autosaves cannot produce an unrecoverable mixed authority;
  • renderer changes cannot bypass the admission mechanism.

Record identity binding — incorporates #361

Protected ciphertext must be cryptographically or structurally bound to the logical record it represents so valid ciphertext cannot be substituted between records undetected.

Define stable identities for each protected class, e.g. project/snapshot/image/index/settings credential records. The binding scheme must survive legitimate moves/migrations where intended and must be included in rekey/migration logic.

Plaintext → protected migration

Existing desktop users require an explicit recoverable migration path.

The migration plan must specify:

  • discovery/inventory of legacy plaintext;
  • admission and locking behavior;
  • resumability;
  • staging and durable commit;
  • rollback/recovery behavior;
  • treatment of backups/snapshots/temp files;
  • version compatibility/downgrade behavior;
  • what happens when a record is corrupt or unreadable;
  • when plaintext originals are removed and what durability evidence permits that removal.

Do not delete the only recoverable copy before the protected replacement is durably committed.

Threat / failure matrix

Tests and design evidence must cover at least:

Scenario Required outcome
wrong key/passphrase fail closed; no destructive rewrite
modified ciphertext/tag detected
cross-record substitution detected
interrupted ordinary write old or new valid state; no torn authoritative record
crash during enable/migration resumable/recoverable
crash during rotation resumable/recoverable; no silent mixed-key loss
concurrent autosave during migration admitted/blocked coherently
locked session + legacy plaintext fail according to secure-storage policy, never bypass it silently
disk full / permission failure actionable failure; old durable state preserved where possible
stale temp/journal deterministic recovery
rollback/downgrade explicit supported/blocked behavior
key loss / reset explicit non-deceptive recovery semantics
large project / long migration bounded memory and observable progress/cancellation policy

Headless and packaged evidence

Core behavior must be testable headlessly without Tauri/Qt. Packaged desktop evidence is additionally required for OS/filesystem/key-store integration and destructive lifecycle cases that unit tests cannot establish.

Evidence maturity must be explicit (LOCAL_ONLY, CI_ONLY, PACKAGED_LOCAL, PACKAGED_TARGET_ENV, FIELD_OBSERVED).

Qt migration relationship

R-15 is pre-Qt / parallel-to-Qt foundation work, not sunk cost. Qt should consume the same Core storage authority rather than reimplementing it.

  • Qt Beta admission is blocked until the required R-15 desktop security/data-integrity contract is implemented and evidenced.
  • Tauri may remain transitional while Core work lands, provided UI/docs remain truthful about what is and is not encrypted.
  • Tauri retirement must not strand plaintext or renderer-private encrypted data.

Related issues / reconciliation

Historical detailed requirements:

Those issues remain useful provenance and detailed threat evidence. R-15/#445 is the canonical integration/closure issue. When implementation lands, reconcile each child requirement explicitly; do not close them merely because #445 has code.

Related migration acceptance: #332 and the Qt/Tauri roadmap documentation.

Acceptance criteria

Non-goals

  • preserving obsolete Tauri-specific crypto architecture for its own sake;
  • weakening durability/security to accelerate Qt;
  • claiming full-disk or OS-account protection beyond the actual threat model;
  • hiding unsupported downgrade/key-loss behavior behind optimistic UX.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions