commit 5c22ceeaebfca8dd25c867c84851860b9ded8c4d
parent cc2b3b030ed2aaf4e370f3b5a7b60cdf012b9770
Author: triesap <tyson@radroots.org>
Date: Wed, 22 Jul 2026 21:02:53 +0000
sqlite: enforce registry bundled runtime
- remove the deleted sibling libsqlite3-sys source override
- lock libsqlite3-sys 0.37.0 to its crates.io checksum
- reject local patches and ambiguous SQLite lock entries
- retain SQLx bundled-runtime and alternative-runtime guards
Diffstat:
4 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -3574,6 +3574,8 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
version = "0.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
dependencies = [
"cc",
"pkg-config",
@@ -5512,6 +5514,7 @@ dependencies = [
"serde_json",
"sqlx",
"thiserror 2.0.18",
+ "toml 0.8.23",
"uuid",
]
diff --git a/Cargo.toml b/Cargo.toml
@@ -73,4 +73,3 @@ unsafe_code = "forbid"
[patch.crates-io]
block = { path = "vendor/block" }
-libsqlite3-sys = { path = "../lib/crates/libsqlite3_sys_3_53_3" }
diff --git a/crates/store/Cargo.toml b/crates/store/Cargo.toml
@@ -26,5 +26,8 @@ uuid.workspace = true
[features]
test-support = []
+[dev-dependencies]
+toml.workspace = true
+
[lints]
workspace = true
diff --git a/crates/store/src/source_guards.rs b/crates/store/src/source_guards.rs
@@ -4,8 +4,10 @@ use std::{
};
const WORKSPACE_SQLX_DEPENDENCY: &str = r#"sqlx = { version = "0.9.0", default-features = false, features = ["derive", "sqlite-bundled"] }"#;
-const WORKSPACE_LIBSQLITE3_PATCH: &str =
- r#"libsqlite3-sys = { path = "../lib/crates/libsqlite3_sys_3_53_3" }"#;
+const LIBSQLITE3_SYS_VERSION: &str = "0.37.0";
+const LIBSQLITE3_SYS_SOURCE: &str = "registry+https://github.com/rust-lang/crates.io-index";
+const LIBSQLITE3_SYS_CHECKSUM: &str =
+ "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1";
#[test]
fn app_sqlite_runtime_uses_sqlx_bundled_sqlite_only() {
@@ -16,9 +18,24 @@ fn app_sqlite_runtime_uses_sqlx_bundled_sqlite_only() {
workspace_manifest.contains(WORKSPACE_SQLX_DEPENDENCY),
"workspace SQLx dependency must stay pinned to SQLx 0.9.0 with sqlite-bundled"
);
+
+ let manifest: toml::Value =
+ toml::from_str(workspace_manifest.as_str()).expect("workspace Cargo.toml should parse");
+ let libsqlite3_patch = manifest
+ .get("patch")
+ .and_then(|patch| patch.get("crates-io"))
+ .and_then(|crates_io| crates_io.get("libsqlite3-sys"));
assert!(
- workspace_manifest.contains(WORKSPACE_LIBSQLITE3_PATCH),
- "workspace must keep the approved SQLite 3.53.3 libsqlite3-sys patch"
+ libsqlite3_patch.is_none(),
+ "workspace must resolve libsqlite3-sys from crates.io without a source override"
+ );
+
+ let lockfile = read_source(app_root.join("Cargo.lock").as_path());
+ let lockfile_findings = libsqlite3_lock_findings(lockfile.as_str());
+ assert!(
+ lockfile_findings.is_empty(),
+ "app SQLite lockfile findings:\n{}",
+ lockfile_findings.join("\n")
);
let findings = sqlite_runtime_drift_findings(app_root.as_path());
@@ -29,6 +46,50 @@ fn app_sqlite_runtime_uses_sqlx_bundled_sqlite_only() {
);
}
+fn libsqlite3_lock_findings(lockfile: &str) -> Vec<String> {
+ let lock: toml::Value = match toml::from_str(lockfile) {
+ Ok(lock) => lock,
+ Err(error) => return vec![format!("Cargo.lock is not valid TOML: {error}")],
+ };
+ let packages = lock
+ .get("package")
+ .and_then(toml::Value::as_array)
+ .map(Vec::as_slice)
+ .unwrap_or_default();
+ let libsqlite3_packages = packages
+ .iter()
+ .filter(|package| {
+ package.get("name").and_then(toml::Value::as_str) == Some("libsqlite3-sys")
+ })
+ .collect::<Vec<_>>();
+
+ if libsqlite3_packages.len() != 1 {
+ return vec![format!(
+ "Cargo.lock must contain exactly one libsqlite3-sys package, found {}",
+ libsqlite3_packages.len()
+ )];
+ }
+
+ let package = libsqlite3_packages[0];
+ let expected_fields = [
+ ("version", LIBSQLITE3_SYS_VERSION),
+ ("source", LIBSQLITE3_SYS_SOURCE),
+ ("checksum", LIBSQLITE3_SYS_CHECKSUM),
+ ];
+ expected_fields
+ .into_iter()
+ .filter_map(|(field, expected)| {
+ let actual = package.get(field).and_then(toml::Value::as_str);
+ (actual != Some(expected)).then(|| {
+ format!(
+ "libsqlite3-sys {field} must be `{expected}`, found `{}`",
+ actual.unwrap_or("<missing>")
+ )
+ })
+ })
+ .collect()
+}
+
fn sqlite_runtime_drift_findings(app_root: &Path) -> Vec<String> {
sqlite_guard_paths(app_root)
.into_iter()
@@ -56,6 +117,7 @@ fn forbidden_sqlite_findings(path: &str, source: &str) -> Vec<String> {
}
for pattern in [
+ "libsqlite3-sys = { path =",
"sqlite-wasm-rs",
"rsqlite-vfs",
"bundled-sqlcipher",
@@ -80,6 +142,30 @@ fn forbidden_sqlite_findings(path: &str, source: &str) -> Vec<String> {
findings
}
+#[test]
+fn sqlite_lock_guard_rejects_local_or_ambiguous_sources() {
+ let valid = format!(
+ r#"[[package]]
+name = "libsqlite3-sys"
+version = "{LIBSQLITE3_SYS_VERSION}"
+source = "{LIBSQLITE3_SYS_SOURCE}"
+checksum = "{LIBSQLITE3_SYS_CHECKSUM}"
+"#
+ );
+ assert!(libsqlite3_lock_findings(valid.as_str()).is_empty());
+
+ let local = format!(
+ r#"[[package]]
+name = "libsqlite3-sys"
+version = "{LIBSQLITE3_SYS_VERSION}"
+"#
+ );
+ assert_eq!(libsqlite3_lock_findings(local.as_str()).len(), 2);
+
+ let duplicate = format!("{valid}\n{valid}");
+ assert_eq!(libsqlite3_lock_findings(duplicate.as_str()).len(), 1);
+}
+
fn sqlite_guard_paths(app_root: &Path) -> Vec<PathBuf> {
let mut paths = vec![app_root.join("Cargo.toml"), app_root.join("Cargo.lock")];
collect_guard_paths(app_root.join("crates").as_path(), &mut paths);