Explain a setting that was never saved, from its defaults
ci / fork-checks (pull_request) Successful in 20s
ci / build (pull_request) Successful in 7m26s

A singleton such as x:SpamSettings has no stored object until someone
saves it; /get shows its defaults instead. Explain looked only for the
stored object, so every setting still at its defaults answered "No
such x:SpamSettings." It now falls back to the defaults the same way.
This commit is contained in:
2026-09-26 01:09:46 -07:00
parent d9a6db025b
commit 866d7d3ed5
2 changed files with 32 additions and 4 deletions
+24 -1
View File
@@ -25,7 +25,7 @@ use registry::{
Role,
},
},
types::EnumImpl,
types::{EnumImpl, id::ObjectId},
};
use serde_json::{Value, json};
use std::time::Duration;
@@ -95,6 +95,29 @@ pub async fn test(test: &mut TestServer) {
assert!(user.contains("Current value: true"), "{user}");
assert!(user.contains("-----BEGIN DETAILS "), "{user}");
// A singleton never saved is explained with its defaults, as /get shows it
let spam_settings = ObjectId::new(ObjectType::SpamSettings, Id::singleton());
assert!(
test.server
.registry()
.get(spam_settings)
.await
.unwrap()
.is_none(),
"x:SpamSettings is stored; pick a singleton the suite never saves"
);
stub.set(Mode::Answer("Mail scoring this much is spam.".into()));
let (created, failed) = admin
.explain(json!({"@type": "Setting", "object": "x:SpamSettings",
"id": "singleton", "property": "scoreSpam"}))
.await;
created.unwrap_or_else(|| panic!("unsaved singleton: {failed}"));
let (_, user) = messages(&stub.last().1);
assert!(
user.contains("Current value: 5"),
"unsaved singleton: {user}"
);
// Acceptance test 7: a secret setting is refused, not masked (EX-9)
let before = stub.count();
for (object, property) in [("x:AiModel", "httpAuth"), ("x:AcmeProvider", "accountKey")] {