commit e3bb612d4410aa0dcdee75d0523923eb54d65a35
parent 741c42a66bf32960176408e1a58af920add9b9c8
Author: triesap <tyson@radroots.org>
Date: Mon, 6 Jul 2026 01:50:09 +0000
knowledge-sdk: align wiki title optionality
Diffstat:
2 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/crates/sdk/src/knowledge.rs b/crates/sdk/src/knowledge.rs
@@ -34,7 +34,7 @@ pub use radroots_events::{
RadrootsKnowledgeSource, RadrootsKnowledgeValidationError, RadrootsRightsAssertion,
RadrootsWikiArticle, RadrootsWikiArticleVersionRef, RadrootsWikiDTagError,
RadrootsWikiMergeRequest, RadrootsWikiRedirect, normalize_wiki_d_tag,
- validate_knowledge_claim, validate_wiki_d_tag,
+ validate_knowledge_claim, validate_wiki_article, validate_wiki_d_tag,
},
};
pub use radroots_events_codec::{
@@ -257,16 +257,18 @@ impl RadrootsWikiArticleBuilder {
pub fn build(self) -> Result<RadrootsWikiArticle, RadrootsKnowledgeBuilderError> {
validate_builder_wiki_d_tag(&self.d_tag)?;
- Ok(RadrootsWikiArticle {
+ let article = RadrootsWikiArticle {
d_tag: self.d_tag,
- title: builder_required_string(self.title, "title")?,
+ title: self.title,
content_djot: builder_required_string(self.content_djot, "content_djot")?,
summary: self.summary,
topics: self.topics,
references: self.references,
forked_from: self.forked_from,
deferred_to: self.deferred_to,
- })
+ };
+ validate_wiki_article(&article).map_err(builder_validation_error)?;
+ Ok(article)
}
pub fn build_event(self) -> Result<WireEventParts, RadrootsSdkKnowledgeError> {
@@ -1347,6 +1349,6 @@ pub mod prelude {
prepare_knowledge_relation_draft, prepare_knowledge_review_draft,
prepare_knowledge_source_draft, prepare_wiki_article_draft,
prepare_wiki_merge_request_draft, prepare_wiki_redirect_draft, validate_knowledge_claim,
- validate_wiki_d_tag, verify_and_decode_radroots_event,
+ validate_wiki_article, validate_wiki_d_tag, verify_and_decode_radroots_event,
};
}
diff --git a/crates/sdk/tests/knowledge_public_api.rs b/crates/sdk/tests/knowledge_public_api.rs
@@ -87,6 +87,36 @@ fn fluent_builders_reject_missing_and_invalid_required_fields() {
}
#[test]
+fn wiki_article_builder_accepts_missing_title_but_rejects_blank_title() {
+ let article = RadrootsWikiArticleBuilder::new("soil-health")
+ .content_djot("# Soil health")
+ .build()
+ .expect("title-free article");
+ assert_eq!(article.title, None);
+
+ let parts = RadrootsWikiArticleBuilder::new("soil-health")
+ .content_djot("# Soil health")
+ .build_event()
+ .expect("title-free article parts");
+ assert!(
+ !parts
+ .tags
+ .iter()
+ .any(|tag| tag.first().map(String::as_str) == Some("title"))
+ );
+
+ let blank_title = RadrootsWikiArticleBuilder::new("soil-health")
+ .title(" ")
+ .content_djot("# Soil health")
+ .build()
+ .expect_err("blank title");
+ assert_eq!(
+ blank_title,
+ RadrootsKnowledgeBuilderError::MissingField("title")
+ );
+}
+
+#[test]
fn knowledge_claim_builder_enforces_citation_rules() {
let missing_citations = RadrootsKnowledgeClaimBuilder::new()
.claim_type("practice_effect")
@@ -278,7 +308,7 @@ fn address_ref() -> RadrootsAddressableRef {
fn wiki_article() -> RadrootsWikiArticle {
RadrootsWikiArticle {
d_tag: "soil-health".to_owned(),
- title: "Soil health".to_owned(),
+ title: Some("Soil health".to_owned()),
content_djot: "# Soil health".to_owned(),
summary: Some("Living soil basics".to_owned()),
topics: vec!["soil".to_owned(), "local-food".to_owned()],