chore: better encrypted sqlite ergonomics#23231
Merged
Merged
Conversation
Replaces consumer-side string matching against sqlite3mc's "file is not
a database" family of messages with a typed error class carrying a
discriminant `code`. Three codes:
- invalid_key_length (pre-flight: key != 32 bytes)
- encryption_not_supported_for_ephemeral
(pre-flight: ephemeral + key)
- decrypt_failed (runtime: sqlite3mc page-1 decode failed —
covers both wrong-key and no-key-on-
encrypted-DB; sqlite3mc does not
distinguish them on the wire)
The worker-to-main wire protocol gains an optional `encryptionCode` field
on `err` responses. The worker tags responses on the catch path; the main
thread re-throws as `SqliteEncryptionError` when the tag is present. Non-
encryption error paths are unchanged — they continue to raise plain
`Error` as before, so this is a non-breaking extension.
Strengthens the existing wrong-key / no-key / short-key / ephemeral+key
tests in encrypted_store.test.ts to assert on the typed class + code.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Builds on the typed SqliteEncryptionError landed in the previous commit
to give the embedded wallet a one-call helper that opens its two stores
(PXE state + walletDB) encrypted-at-rest, with cohesive failure handling.
Adds:
- EmbeddedWalletEncryptionError extends Error
readonly storeName: 'pxe' | 'wallet'
cause: SqliteEncryptionError
Lets callers drive recovery UX based on WHICH store failed — PXE
state is typically safer to wipe-and-rebuild from L1 than walletDB,
which holds the user's accounts and senders.
- openEncryptedEmbeddedStores(config, getEncryptionKey, log)
Opens both stores in sequence with the same key callback (invoked
once per store — required because AztecSQLiteOPFSStore.open transfers
the key buffer to its worker and detaches the caller's view).
On PXE decrypt failure: throws EmbeddedWalletEncryptionError(pxe);
nothing to clean up.
On wallet decrypt failure: closes the already-opened PXE store
(best-effort, swallowing close() errors so the original surfaces),
then throws EmbeddedWalletEncryptionError(wallet).
On any non-decrypt error during the wallet open: still closes PXE,
but re-throws the original error unwrapped — keeps the typed-error
contract narrow to encryption-shaped failures.
Re-exported only from the browser entrypoint (sqlite3mc requires Web
Workers + OPFS); the node entrypoint uses LMDB and does not surface this.
The `openStore` parameter on the helper is an `@internal` DI seam for
tests (defaults to AztecSQLiteOPFSStore.open). Without it, unit tests
would require a browser environment the wallets package doesn't set up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two `if (...) return` lines tripped the workspace's `curly` rule. Wrap both bodies in braces. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nges
Two CI failures surfaced when this PR's commits landed on top of the
recent next merge into merge-train/fairies. Both fixed here.
(1) playground/vite.config.ts: chunk-size-validator's `closeBundle` hook
fired before vite/rollup had flushed any output to disk, so the
`scandirSync('dist')` inside the validator failed with ENOENT on a build
that had otherwise transformed all modules cleanly. Switching to the
`writeBundle` hook (documented to run AFTER bundle is on disk) restores
the original intent. The previous behavior was an artifact of the
vite/rollup version bump that came in via the merge — `closeBundle` is
no longer guaranteed to run post-write in current vite. `writeBundle`
is the correct hook for "check what was just written" semantics.
(2) Moved openEncryptedEmbeddedStores + types from being re-exported by
`wallets/embedded/entrypoints/browser.ts` to a dedicated package
sub-path `@aztec/wallets/embedded/store-encryption`. Reason: every
consumer importing from `@aztec/wallets/embedded` (e.g. the playground,
which only uses `EmbeddedWallet`) was transitively pulling in
`@aztec/kv-store/sqlite-opfs` and its
`new Worker(new URL('./worker.js', import.meta.url))` chain into
`@aztec/sqlite3mc-wasm`. Vite's worker plugin then tries to bundle the
worker entrypoint statically, and since playground's
`vite-plugin-node-polyfills` only applies to the main bundle (not the
worker context), the build fails with "Rollup failed to resolve import
'vite-plugin-node-polyfills/shims/process'". The sub-path split keeps
the encryption-at-rest helper a real first-class API but ensures only
consumers that explicitly opt into it pay the bundle cost.
After (1): playground's chunk-size-validator now reports correctly
("Validating chunk sizes... index-*.js: 1789.59 KB / 1850 KB").
After (2): playground's main entrypoint drops by ~43 KB because the
sqlite-opfs import chain is no longer reachable from
@aztec/wallets/embedded. Net main bundle: 1789.59 KB (within limit).
All 24 wallets tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Flakey Tests🤖 says: This CI run detected 1 tests that failed, but were tolerated due to a .test_patterns.yml entry. |
AztecBot
pushed a commit
that referenced
this pull request
May 13, 2026
Adds some structure to typical decryption errors, and a couple of convenience helpers for orchestrating encrypted store management from embedded wallet, so that the most basic usage is straightforward and downstream projects don't need to rewrite the same lines over and over. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
|
✅ Successfully backported to backport-to-v4-next-staging #23236. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds some structure to typical decryption errors, and a couple of convenience helpers for orchestrating encrypted store management from embedded wallet, so that the most basic usage is straightforward and downstream projects don't need to rewrite the same lines over and over.