Skip to content

Snapshot live SQLite stores before querying#102

Open
jmcte wants to merge 3 commits into
mainfrom
codex/issue-90-sqlite-snapshots
Open

Snapshot live SQLite stores before querying#102
jmcte wants to merge 3 commits into
mainfrom
codex/issue-90-sqlite-snapshots

Conversation

@jmcte

@jmcte jmcte commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • snapshot live SQLite databases with present WAL/SHM companions into private temporary storage before querying
  • enforce read-only/query-only execution, bounded busy/process timeouts, structured failures, and deterministic cleanup
  • migrate Messages and Safari history first and document the remaining provider migration queue

Governing Issue

Closes #90

Validation

  • Relevant local checks passed
  • Required PR checks are expected to satisfy CI Gate
  • Skipped checks are explained below

swift test --disable-sandbox — 113 tests passed

bash scripts/ci/run-fast-checks.sh — passed; source line coverage 88.95%, mutation checks killed expected mutations, debug and release builds passed

WAL-backed rows, missing companions, query-only rejection, locked/busy stores, timeout, copy permission failure, schema drift, and cleanup are covered with synthetic tests.

Bootstrap Governance

  • Changes are scoped to the linked issue
  • Contributor or PR guidance changes are reflected in CONTRIBUTING.md, .github/PULL_REQUEST_TEMPLATE.md, and docs/bootstrap/onboarding.md when applicable
  • PR author enabled auto-merge where GitHub allows it, or GitHub plan-limit evidence/unavailable reason is recorded and the fallback merge-readiness policy applies
  • No real secrets, runtime auth, or machine-local env files are committed

This branch is stacked on provider-manifest PR #101. The PR remains draft until #101 merges and the diff collapses to the issue #90 commit; auto-merge will then be armed.

Flow Contract

  • Owner lane: Hermes macOS/native storage safety
  • Repair owner: jmcte
  • Autonomy class: review-gated implementation from assigned issue
  • Risk class: security; high-sensitivity private-store copy and process-lifecycle behavior

Flow Merge Readiness

  • Every blocker has a next actor and next action
  • No active blocking requested changes remain
  • Non-author approval is present when required
  • PR author enabled auto-merge where GitHub allows it, or recorded why it is unavailable/unsafe

Next actor: #101 reviewers, then security/architecture/macOS reviewers on this PR.

Merge Automation

  • PR author enabled auto-merge with gh pr merge --auto --squash, or the reason it is unavailable/unsafe is noted below

Auto-merge is intentionally deferred while the PR is draft and stacked on #101.

Notes

  • Private copies and query output use restrictive permissions and are deleted before return or error.
  • The source database is never checkpointed, locked, vacuumed, or modified.

Expose a deterministic metadata-only provider registry through JSON and text output, covering every current Apple-data command family with maturity, source, permission, sensitivity, capability, and polling declarations. Document the v1 compatibility policy.\n\nCloses #89.
Add a private read-only SQLite snapshot engine with WAL and SHM companions, query-only enforcement, busy and process timeouts, structured failures, and deterministic cleanup. Migrate Messages and Safari history and document remaining providers.\n\nCloses #90.
@jmcte
jmcte requested a review from pheidon July 11, 2026 21:54
@jmcte

jmcte commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@athena-omt @pheidon @ares-omt @Hermes-omt — this security-sensitive SQLite snapshot PR is stacked on #101 and intentionally draft until that dependency merges. Early review is welcome on WAL consistency, private temporary storage, query-only enforcement, timeout/termination behavior, cleanup, and source-path error mapping.

@jmcte
jmcte marked this pull request as ready for review July 12, 2026 07:29
@jmcte
jmcte requested a review from a team as a code owner July 12, 2026 07:29
@jmcte
jmcte enabled auto-merge (squash) July 12, 2026 19:39
@jmcte jmcte mentioned this pull request Jul 12, 2026
12 tasks

@Hermes-omt Hermes-omt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Core design is sound — 113 tests pass, CI green. However, four edge cases should be addressed:

1. No production timeout floor (Medium)

SQLiteSnapshotQueryEngine accepts timeout down to 0.001s and busyTimeoutMilliseconds can be zero. For production SQL providers under concurrent iCloud access, these values are too aggressive.
Action: Add a factory wrapper or static builder that enforces minimums for production use (e.g., timeout ≥ 5s, busyTimeout ≥ 500ms), or document the constraint clearly in sqlite-snapshots.md.

2. TerminationHandler race (Low)

The termination handler signals a semaphore but doesn't guard against process.terminate() racing with early completion. On some macOS versions terminate can fail silently.
Action: Check process.isRunning before calling terminate, or handle the error path explicitly in the timeout case.

3. SQLite -readonly WAL mode constraint (Low)

Pre-3.14 sqlite3 had a known issue with -readonly and WAL databases. macOS Monterey+ is safe, but document as a minimum version requirement.
Action: Add a note to sqlite-snapshots.md noting the minimum sqlite3 version (≥ 3.14) or confirm via runtime check.

4. Missing .tmp journal cleanup (Low)

If an external sqlite3 process crashes in /tmp before our snapshot dir is created, the orphaned .tmp file persists outside our cleanup scope.
Action: Very low risk; optionally note in docs that concurrent sqlite3 access to the same temp root requires coordination.

CI Status

  • ✅ CI Gate: success
  • ✅ PR Checks: success
  • ⚠️ No non-author approvals yet (this is the first review)

Overall: Solid engineering. These are refinements, not blockers — but I'm requesting changes so the author can address them before auto-merge fires.

@Hermes-omt Hermes-omt added the state:needs-repair PR needs repair before review can proceed. label Jul 17, 2026
…-snapshots

# Conflicts:
#	Sources/ICloudCLICore/CommandLine.swift
#	Sources/ICloudCLICore/CommandRunner.swift
#	Sources/ICloudCLICore/ProviderManifest.swift
#	Tests/ICloudCLICoreTests/ProviderManifestTests.swift
#	docs/provider-manifest.md
@athena-omt athena-omt added status:needs-review PR is ready for Athena review. review:athena Athena review governance requested. state:waiting-checks Waiting for CI/check status to settle. and removed state:needs-repair PR needs repair before review can proceed. labels Jul 17, 2026

@Hermes-omt Hermes-omt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

SQLiteSnapshotQueryEngine.withSnapshot uses FileManager.copyItem(at: source, ...), which preserves symbolic links on macOS. Both migrated call paths accept caller-supplied --chat-db and --history-db; when either is a symlink, snapshot.sqlite remains a link to the live database. Companion lookup also uses the link pathname, so it can omit the target store's -wal/-shm files. This breaks the private, consistent-snapshot guarantee for a supported input.

Resolve the source with resolvingSymlinksInPath() before existence checks, copying, and companion derivation (while retaining the original path for reportedStore), or explicitly reject symlink inputs. Add a fixture test proving a symlinked WAL-backed source produces a regular snapshot and reads the target's committed WAL row.

Validated on the exact head: swift test --disable-sandbox passed 117 tests; GitHub PR Fast CI is successful.

@Hermes-omt Hermes-omt added state:needs-repair PR needs repair before review can proceed. and removed status:needs-review PR is ready for Athena review. review:athena Athena review governance requested. state:waiting-checks Waiting for CI/check status to settle. labels Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:needs-repair PR needs repair before review can proceed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v2: Snapshot live SQLite stores consistently before querying

4 participants