diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index 3226d3c..02b48a8 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -969,4 +969,56 @@ mod tests { ); } } + + /// `build.rs` derives the AppManifest from the handler list and this reads back what + /// tauri-build actually embedded. `cargo test` runs the build script first, so + /// `gen/schemas/acl-manifests.json` is fresh. Independent of the shared parser: if + /// `registered_commands` ever lost half the list, `build.rs` would declare half a + /// manifest and this would still compare it against… the same half. So the count is + /// pinned too, from a source that is not the parser: the `#[tauri::command]` scan in + /// `every_command_is_registered_exactly_once` guarantees definitions == registrations, + /// and here the embedded set must match the number of registrations that scan found. + #[test] + fn the_generated_app_manifest_matches_the_handler_list() { + use std::collections::BTreeSet; + + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/gen/schemas/acl-manifests.json"); + let raw = std::fs::read_to_string(path) + .expect("gen/schemas/acl-manifests.json is written by build.rs on every build"); + let manifests: serde_json::Value = + serde_json::from_str(&raw).expect("acl-manifests.json must parse"); + let app = manifests.get("__app-acl__").expect( + "build.rs must declare an AppManifest — without it tauri skips the ACL for every \ + app command", + ); + let embedded: BTreeSet = app["permissions"] + .as_object() + .expect("the app manifest has a permissions map") + .keys() + .cloned() + .collect(); + + let registered = crate::command_census::registered_commands(include_str!("lib.rs")) + .expect("lib.rs should contain a generate_handler! list"); + let expected: BTreeSet = registered + .iter() + .flat_map(|c| { + let allow = crate::command_census::allow_permission(c); + let deny = format!("deny-{}", &allow["allow-".len()..]); + [allow, deny] + }) + .collect(); + + assert!(registered.len() >= 100, "the parser sees {} commands", registered.len()); + assert_eq!( + embedded, expected, + "the embedded app manifest and generate_handler! disagree: build.rs and \ + tauri-build should have produced the same list" + ); + assert!( + app["permission_sets"].as_object().is_some_and(|s| s.is_empty()), + "no permission sets: every grant is a literal allow-* string in a capability file" + ); + assert!(app["default_permission"].is_null(), "no app `default` permission set"); + } }