//! Bootstrap proofs cannot survive registration. Typed overrides reject misspelled limits. use sausage::cred::{ items::{Field, Item}, requests::{GrantRequest, Overrides}, webauthn::{Decision, Unlocked}, *, }; fn fixture() -> (tempfile::TempDir, Cred, Caller, Item, String, Unlocked) { let dir = tempfile::tempdir().unwrap(); let c = Cred::open(dir.path()).unwrap(); let proof = c.unlocked().unwrap(); let caller = Caller { program: "/bin/test.wasm".into(), pid: 1, conversations: vec!["root".into()], }; let item = c .create_item( Item { id: String::new(), name: "test".into(), version: 0, free_use: false, rules: vec![], validate_js: None, transform_js: String::new(), fields: vec![Field { field_id: String::new(), name: "secret".into(), public: false, value: None, needs_value: true, field_type: types::FieldType::Text, key_type: None, }], }, &caller, proof, ) .unwrap(); let id = c .file_request( &caller, "request", GrantRequest { items: vec![item.id.clone()], duration_secs: None, max_uses: None, validator: None, }, ) .unwrap(); let db = rusqlite::Connection::open(dir.path().join("cred.sqlite")).unwrap(); db.execute( "INSERT INTO passkey_credentials VALUES('synthetic','test','{}')", [], ) .unwrap(); (dir, c, caller, item, id, proof) } #[test] fn registered_passkey_refuses_unlocked_approval() { let (_dir, c, _caller, _item, id, proof) = fixture(); assert!( c.approve(&id, Decision::Approve, Overrides::default(), proof) .is_err() ); assert_eq!(c.request_list().unwrap()[0].state, "pending"); assert!(c.unlocked().is_err()); } #[test] fn registered_passkey_refuses_unlocked_denial() { let (_dir, c, _caller, _item, id, proof) = fixture(); assert!(c.deny(&id, Decision::Deny, proof).is_err()); } #[test] fn registered_passkey_refuses_direct_mutations() { let (_dir, c, caller, item, _id, proof) = fixture(); assert!( c.set_field( &item.id, &item.fields[0].field_id, "synthetic", &caller, proof ) .is_err() ); assert!( c.create_item( Item { name: "another".into(), ..item }, &caller, proof ) .is_err() ); assert!( c.revoke_subjects(&caller.conversations, &caller, proof) .is_err() ); } #[test] fn overrides_reject_unknown_fields() { assert!(serde_json::from_value::(serde_json::json!({"max_use":1})).is_err()); }