Skip to content

Complete internal termsnip→terminal-workspace rename: SQLite db file + Tauri command/event prefix #129

Description

@deffenda

Context

#115 renamed the data-facing identifiers (localStorage key namespace → terminal-workspace-*, config bundle app: "Terminal Workspace" / v5) behind a tested forward-migration. Two internal identifier groups were deliberately deferred there because they are native-only, carry no user-facing benefit, and cannot be verified by the browser/demo test suite:

  1. SQLite db file — still sqlite:termsnip.db (persistence.ts, tauri.conf.json preload, main.rs). Renaming needs a one-time native file-copy migration (copy old→new if new absent; keep old one release for rollback).
  2. Tauri command prefix termsnip_* (≈38 commands) + events termsnip://* (2) — an internal JS↔Rust contract. Renaming must be lockstep across Rust (#[tauri::command] fns + invoke_handler + emit) and JS (invokeTauriCommand strings + listen).

Why this is NOT ready (left in backlog)

  • No user-facing benefit — these identifiers are invisible; this is pure internal consistency.
  • Unverifiable in the harness — the test suite runs browser/demo (mocked) transport and never invokes a real Tauri command or the native db. A single missed JS↔Rust site would break every existing native install at runtime with the full suite still green. cargo check catches Rust-internal mismatch (fn vs invoke_handler) but NOT JS↔Rust drift.
  • Needs on-device verification — a maintainer must run a native tauri dev/build and confirm commands, events, sessions, and persisted data all work post-rename.

Done-when (when promoted)

{
  "scope": [
    "apps/desktop/src/components/layout/AppShell.tsx",
    "apps/desktop/src/components/terminal/TerminalPane.tsx",
    "apps/desktop/src/components/terminal/TerminalTabView.tsx",
    "apps/desktop/src/hooks/useAutoUpdateCheck.ts",
    "apps/desktop/src/lib/api.test.ts",
    "apps/desktop/src/lib/demo-backend.ts",
    "apps/desktop/src/lib/persistence.test.ts",
    "apps/desktop/src/lib/persistence.ts",
    "apps/desktop/src/lib/vault-sync-contract.test.ts",
    "apps/desktop/src/lib/vault-sync-contract.ts",
    "apps/desktop/src/lib/vault-sync-runtime.test.ts",
    "apps/desktop/src/routes/KeysPage.tsx",
    "apps/desktop/src/routes/SettingsPage.tsx",
    "apps/desktop/src/store/vault-sync-trust-store.test.ts",
    "apps/desktop/src/store/vault-sync-trust-store.ts",
    "apps/desktop/src/types/key.ts",
    "changelog.d/129-complete-internal-termsnip-terminal-workspace-rename-sqlite-db-file-tauri-comman.md",
    "scripts/backend-transport-test.sh",
    "scripts/generate-tauri-icons.sh",
    "scripts/native-dmg.sh",
    "scripts/native-fixture-preflight.sh",
    "scripts/native-notarize.sh",
    "src-tauri/src/keychain_support.rs",
    "src-tauri/src/main.rs",
    "src-tauri/src/native_host_keys.rs",
    "src-tauri/src/native_transport.rs",
    "src-tauri/src/native_transport_fixtures.rs",
    "src-tauri/tauri.conf.json",
    "tests/e2e/onboarding.spec.ts",
    "tests/integration/backend-auth.integration.test.ts",
    "tests/integration/github-release-secrets.integration.test.ts",
    "tests/integration/keygen-passphrase-leak.integration.test.ts",
    "tests/integration/ssh.integration.test.ts",
    "tests/integration/static-root-containment.integration.test.ts"
  ],
  "depends_on": [],
  "done_when": [
    "the SQLite database is renamed termsnip.db -> terminalworkspace.db with a native copy-migration (old -> new only when new is absent), and the old file is retained for one release so rollback is possible",
    "the copy-migration is CRASH-SAFE: whatever file the idempotence guard tests must be the LAST artifact created, so an interruption cannot leave a database present without its -wal/-shm sidecars. A crash mid-migration must either retry cleanly on next launch or leave the legacy database authoritative - never silently open a db whose un-checkpointed WAL was not carried over. This matters because #329 enabled WAL, so a populated -wal is the normal state, not an edge case",
    "Tauri command prefix termsnip_* and events termsnip://* are renamed in lockstep across Rust (#[command] fns, invoke_handler, emit) and JS (invoke strings, listen), with the before/after command+event name SETS proven identical - a rename must not add or drop a name",
    "zero residual termsnip_ command or termsnip:// event references remain, excluding the migration's intentional reads of the old database name",
    "TEST EXPECTATIONS MAY MOVE: this rename forces literal-string updates in the test files named in scope (api.test.ts, persistence.test.ts, vault-sync-*.test.ts, vault-sync-trust-store.test.ts, tests/e2e/onboarding.spec.ts, tests/integration/*.integration.test.ts). This clause explicitly authorizes changing those expectations to the new names, and cites itself as the authorization; no other assertion may be weakened",
    "bash scripts/validate.sh exits 0"
  ],
  "validation": {
    "local": [
      "bash scripts/validate.sh"
    ],
    "review": []
  },
  "checks": [
    {
      "type": "absent",
      "for": 2,
      "path": "src-tauri/src/main.rs",
      "pattern": "termsnip_",
      "why": "the command prefix must be gone from the Rust surface; a partial rename that leaves invoke_handler entries behind breaks the JS bridge silently"
    },
    {
      "type": "absent",
      "for": 2,
      "path": "apps/desktop/src/lib/api.ts",
      "pattern": "termsnip://",
      "why": "the event namespace must be gone from the JS listener surface for the same reason, in the other direction"
    },
    {
      "type": "grep",
      "for": 0,
      "path": "src-tauri/src/main.rs",
      "pattern": "terminalworkspace\\.db",
      "why": "the new database name must actually be referenced, not merely described in the ticket"
    },
    {
      "type": "grep",
      "for": 0,
      "path": "src-tauri/src/main.rs",
      "pattern": "termsnip\\.db",
      "why": "the OLD name must ALSO survive, as the migration's source. Its absence means the copy-migration was dropped and existing users silently start with an empty database"
    },
    {
      "type": "absent",
      "for": 1,
      "path": "src-tauri/src/main.rs",
      "pattern": "fs::copy\\(&legacy_path, &terminal_workspace_path\\)[\\s\\S]{0,400}?copy_legacy_database_sidecar",
      "why": "the defect shape from PR #336: main .db copied BEFORE the sidecars, while the guard tests the main .db. Its absence forces either sidecars-first or an atomic rename-in-last; a presence grep for 'rename' would not catch a reordering that still copies the guard file first"
    }
  ]
}

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3-maintainabilityArchitecture and hygiene. Real value, not north-star blocking.ai/backlogCaptured work; not actively refined yetbreaking-changeAPI or behavior break; blocks auto-mergedo-not-mergeExplicit block on auto-mergemigrationSchema or data migration; blocks auto-mergerisk:highHigh-risk change; escalate AI review to Gemini Protier:ArchitecturalORC suggested model tier: Architectural

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions