Skip to content

Move cursor and backend session state into SQLite #170

Description

@owainlewis

Goal

Reduce Push's mutable sources of truth by storing channel cursors and backend session mappings in the existing canonical SQLite database.

Scope

  • Add schema migrations for channel cursors and channel-qualified backend sessions.
  • Preserve the current monotonic-cursor rule and backend-change session rotation behavior.
  • Replace whole-file JSON rewrites with transactional SQLite operations.
  • Migrate existing state.json data idempotently on startup.
  • Keep the legacy last_row_id and unqualified iMessage-session compatibility rules during migration.
  • Make migration crash-safe: never delete or invalidate the source before the database commit is verified.
  • Retain a recoverable backup or explicit operator recovery path after successful migration.
  • Keep the Slack durable inbox separate unless evidence shows its acknowledgement-queue semantics fit the same database safely.
  • Update backup, recovery, security, architecture, and configuration documentation.

Dependencies

Non-goals

  • Do not merge the append-only audit log into SQLite.
  • Do not change conversation-history retention or add memory summarization.
  • Do not remove compatibility in the same release that introduces migration.

Acceptance criteria

  • Cursor advancement and backend-session changes are transactional.
  • Cursor values never move backwards under concurrent or repeated writes.
  • Existing state.json installations migrate without losing cursors or resumable sessions.
  • Repeating or crashing migration cannot duplicate, regress, or erase state.
  • Backend changes still start fresh sessions and /clear still rotates the exact channel-qualified session.
  • Database or migration failure prevents unsafe polling progress and produces an actionable error.
  • Tests cover legacy iMessage keys, multiple channels, multiple backends, empty session IDs, migration interruption, repeat migration, corrupt JSON, and concurrent cursor writes.
  • Documentation clearly states which data lives in SQLite and how to recover the legacy file.

Verify

  • cargo fmt --all -- --check
  • cargo clippy --locked --all-targets -- -D warnings
  • cargo build --locked
  • cargo test --locked

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-readyScoped enough for an agent to pick upenhancementNew feature or requesthardeningRobustness / correctness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions