commit e9d7d77cc105113afc209cc80949bcfb93ef4aa9
parent c7211babab84f138ee5569e313b04c6c8281cf8c
Author: triesap <tyson@radroots.org>
Date: Mon, 6 Jul 2026 01:50:09 +0000
knowledge-sdk: align wiki title optionality
Diffstat:
4 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/crates/events_codec_wasm/src/lib.rs b/crates/events_codec_wasm/src/lib.rs
@@ -715,7 +715,7 @@ mod tests {
fn sample_wiki_article() -> RadrootsWikiArticle {
RadrootsWikiArticle {
d_tag: "soil-health".to_string(),
- title: "Soil health".to_string(),
+ title: Some("Soil health".to_string()),
content_djot: "# Soil health".to_string(),
summary: Some("Living soil basics".to_string()),
topics: vec!["soil".to_string()],
@@ -1477,6 +1477,20 @@ mod tests {
}
#[test]
+ fn wiki_article_tags_accept_missing_title() {
+ let mut article = sample_wiki_article();
+ article.title = None;
+ let tags = tags_json(wiki_article_tags(
+ &serde_json::to_string(&article).expect("wiki article json"),
+ ));
+ assert!(
+ !tags
+ .iter()
+ .any(|tag| tag.first().map(String::as_str) == Some("title"))
+ );
+ }
+
+ #[test]
fn knowledge_claim_tags_enforce_citation_rules() {
let mut claim = sample_knowledge_claim();
claim.citation_spans.clear();
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()],
diff --git a/packages/events-bindings/src/generated/types.ts b/packages/events-bindings/src/generated/types.ts
@@ -222,7 +222,7 @@ export type RadrootsTradeListingValidateResult = { valid: boolean, errors: Array
export type RadrootsTradeValidationListingError = { kind: "invalid_kind", amount: { kind: number, }, } | { kind: "missing_listing_id", } | { kind: "listing_event_not_found", amount: { listing_addr: string, }, } | { kind: "listing_event_fetch_failed", amount: { listing_addr: string, }, } | { kind: "parse_error", amount: { error: RadrootsListingParseError, }, } | { kind: "invalid_seller", } | { kind: "missing_farm_profile", } | { kind: "missing_farm_record", } | { kind: "missing_title", } | { kind: "missing_description", } | { kind: "missing_product_type", } | { kind: "missing_bins", } | { kind: "missing_primary_bin", } | { kind: "invalid_bin", } | { kind: "missing_price", } | { kind: "invalid_price", } | { kind: "missing_inventory", } | { kind: "invalid_inventory", } | { kind: "missing_availability", } | { kind: "missing_location", } | { kind: "missing_location_locality", } | { kind: "missing_location_geohash", } | { kind: "invalid_location_geohash", } | { kind: "missing_delivery_method", };
-export type RadrootsWikiArticle = { d_tag: string, title: string, content_djot: string, summary?: string | null, topics: Array<string>, references: Array<RadrootsNostrEventRef>, forked_from: Array<RadrootsWikiArticleVersionRef>, deferred_to?: RadrootsWikiArticleVersionRef | null, };
+export type RadrootsWikiArticle = { d_tag: string, title?: string | null, content_djot: string, summary?: string | null, topics: Array<string>, references: Array<RadrootsNostrEventRef>, forked_from: Array<RadrootsWikiArticleVersionRef>, deferred_to?: RadrootsWikiArticleVersionRef | null, };
export type RadrootsWikiArticleVersionRef = { event_id: string, address_ref: RadrootsAddressableRef, };