Open the downloaded snapshot database read-only, on a private temp dir #186

Merged
clawbot merged 1 commits from issue-162-readonly-snapshot-db into next 2026-09-22 12:45:54 +02:00
Collaborator

Closes #162.

Restore and deep verify opened the decrypted snapshot database read-write through the local-index constructor (applying migrations against whatever the file carried) and left it in the shared temp directory.

  • New database.OpenReadOnly: opens the file read-only (mode=ro) with query_only on and trusted_schema=OFF, never applies schema files, and refuses any file whose schema carries a trigger, view or virtual table, or lacks an expected table. Restore and deep verify both use it, so a forged file can no longer redefine what the restore queries return.
  • Each command now writes the decrypted database into its own private (0700) temp directory and removes the whole directory (RemoveAll) on every return path — success, error, and the open failure that previously leaked decrypted metadata. This also sweeps any SQLite side files.
  • Deep verify now checks the error from closing the temp file, matching restore.
  • pickNextDownload returns (FileID, bool), so a genuine file carrying the nil UUID is no longer read as "nothing left"; runRestoreLoop returns an error if any file is still pending once it can make no further progress.

Tests: a view named files is refused, a read-only open rejects writes, the temp dir is 0700, a forced open failure leaves no temp directory, and a nil-UUID file is picked rather than abandoned.

What a reader would trip over: the driver only honours mode=ro via a file: URI DSN, so snapshotReadOnlyDSN builds one. Two //nolint:gosec G304 suppressions cover file opens on a MkdirTemp path plus a constant filename.

Model: opus-4-8

Closes https://git.eeqj.de/sneak/vaultik/issues/162. Restore and deep verify opened the decrypted snapshot database read-write through the local-index constructor (applying migrations against whatever the file carried) and left it in the shared temp directory. - New `database.OpenReadOnly`: opens the file read-only (`mode=ro`) with `query_only` on and `trusted_schema=OFF`, never applies schema files, and refuses any file whose schema carries a trigger, view or virtual table, or lacks an expected table. Restore and deep verify both use it, so a forged file can no longer redefine what the restore queries return. - Each command now writes the decrypted database into its own private (`0700`) temp directory and removes the whole directory (`RemoveAll`) on every return path — success, error, and the open failure that previously leaked decrypted metadata. This also sweeps any SQLite side files. - Deep verify now checks the error from closing the temp file, matching restore. - `pickNextDownload` returns `(FileID, bool)`, so a genuine file carrying the nil UUID is no longer read as "nothing left"; `runRestoreLoop` returns an error if any file is still pending once it can make no further progress. Tests: a view named `files` is refused, a read-only open rejects writes, the temp dir is `0700`, a forced open failure leaves no temp directory, and a nil-UUID file is picked rather than abandoned. What a reader would trip over: the driver only honours `mode=ro` via a `file:` URI DSN, so `snapshotReadOnlyDSN` builds one. Two `//nolint:gosec` G304 suppressions cover file opens on a MkdirTemp path plus a constant filename. Model: opus-4-8
clawbot added the needs-review label 2026-09-22 12:09:40 +02:00
clawbot self-assigned this 2026-09-22 12:09:41 +02:00
Author
Collaborator

PASS

Model: opus-4-8

PASS Model: opus-4-8
clawbot added needs-rebase and removed needs-review labels 2026-09-22 12:29:19 +02:00
clawbot added 1 commit 2026-09-22 12:31:42 +02:00
Restore and deep verify used to open the decrypted snapshot database
read-write through the local-index constructor, which applied migrations
against whatever the file carried, and left the decrypted file in the
shared temp directory. A forged file could redefine what the restore
queries return, and an interrupted open left decrypted metadata on disk.

Add database.OpenReadOnly: opens the file read-only (mode=ro) with
query_only and trusted_schema=OFF, never applies schema files, and
refuses any file whose schema carries a trigger, view or virtual table
or lacks an expected table. Restore and deep verify now both use it.

Each command materializes the database inside its own private (0700)
temp directory and removes the whole directory on every return path, so
the decrypted file and any SQLite side files are always cleaned up.
Deep verify now also checks the error from closing the temp file.

pickNextDownload returns (FileID, bool), so a genuine file carrying the
nil UUID is no longer mistaken for "nothing left"; runRestoreLoop fails
with an error if any file is still pending when it can make no progress.

Model: opus-4-8
clawbot force-pushed issue-162-readonly-snapshot-db from 8e335008cb to 46c295acf3 2026-09-22 12:31:42 +02:00 Compare
Author
Collaborator
-
Author
Collaborator
-
clawbot merged commit a6434de57f into next 2026-09-22 12:45:54 +02:00
clawbot deleted branch issue-162-readonly-snapshot-db 2026-09-22 12:45:54 +02:00
Sign in to join this conversation.