commit bf4ac52aaaca6e23430633fe53b22ac459f10117
parent a547226bd8966beab77325cc9d24abd0845d4651
Author: triesap <tyson@radroots.org>
Date: Fri, 12 Jun 2026 16:35:56 -0700
events_codec_wasm: align hardened tag exports
- rename wasm helpers to the canonical contract names
- keep farm and social tag-builder smoke coverage current
- require farm file support in wasm workspace samples
- document exact wasm helper names in the social event spec
Diffstat:
2 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/crates/events_codec_wasm/src/lib.rs b/crates/events_codec_wasm/src/lib.rs
@@ -190,8 +190,11 @@ pub fn calendar_tags(calendar_json: &str) -> Result<String, RadrootsJsValue> {
build_tags_json::<RadrootsCalendar, _, _>(calendar_json, calendar_collection_build_tags)
}
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = calendar_rsvp_tags))]
-pub fn calendar_rsvp_tags(rsvp_json: &str) -> Result<String, RadrootsJsValue> {
+#[cfg_attr(
+ target_arch = "wasm32",
+ wasm_bindgen(js_name = calendar_event_rsvp_tags)
+)]
+pub fn calendar_event_rsvp_tags(rsvp_json: &str) -> Result<String, RadrootsJsValue> {
build_tags_json::<RadrootsCalendarEventRsvp, _, _>(rsvp_json, rsvp_build_tags)
}
@@ -285,24 +288,27 @@ pub fn gift_wrap_tags(gift_wrap_json: &str) -> Result<String, RadrootsJsValue> {
build_tags_json::<RadrootsGiftWrap, _, _>(gift_wrap_json, gift_wrap_build_tags)
}
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_workspace_tags))]
-pub fn farm_workspace_tags(workspace_json: &str) -> Result<String, RadrootsJsValue> {
+#[cfg_attr(
+ target_arch = "wasm32",
+ wasm_bindgen(js_name = farm_workspace_manifest_tags)
+)]
+pub fn farm_workspace_manifest_tags(workspace_json: &str) -> Result<String, RadrootsJsValue> {
build_tags_json::<RadrootsFarmWorkspaceManifest, _, _>(
workspace_json,
farm_workspace_build_tags,
)
}
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_crdt_tags))]
-pub fn farm_crdt_tags(input_json: &str) -> Result<String, RadrootsJsValue> {
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_crdt_change_tags))]
+pub fn farm_crdt_change_tags(input_json: &str) -> Result<String, RadrootsJsValue> {
let input = parse_json::<FarmCrdtTagsInput>(input_json)?;
let tags = farm_crdt_change_build_tags_with_author(&input.change, Some(&input.author_pubkey))
.map_err(err_js)?;
tags_to_json(tags)
}
-#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_file_tags))]
-pub fn farm_file_tags(file_json: &str) -> Result<String, RadrootsJsValue> {
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen(js_name = farm_file_metadata_tags))]
+pub fn farm_file_metadata_tags(file_json: &str) -> Result<String, RadrootsJsValue> {
build_tags_json::<RadrootsFarmFileMetadata, _, _>(file_json, farm_file_metadata_build_tags)
}
@@ -411,6 +417,7 @@ mod tests {
use radroots_events::http_auth::RadrootsHttpAuth;
use radroots_events::job::JobInputType;
use radroots_events::job_request::{RadrootsJobInput, RadrootsJobParam};
+ use radroots_events::kinds::KIND_FARM_FILE_METADATA;
use radroots_events::listing::{RadrootsListingBin, RadrootsListingProduct};
use radroots_events::relay_auth::RadrootsRelayAuth;
use radroots_events::social::{
@@ -735,7 +742,7 @@ mod tests {
url: "https://media.example.invalid/farm/field-group".to_string(),
service: "RadrootsPrivateMedia".to_string(),
}],
- supported_kinds: vec![78, 30078],
+ supported_kinds: vec![78, 30078, KIND_FARM_FILE_METADATA],
protocol_version: RADROOTS_FARM_WORKSPACE_PROTOCOL_VERSION.to_string(),
created_at_ms: 1_780_000_000_000,
updated_at_ms: None,
@@ -803,7 +810,7 @@ mod tests {
is_restricted: true,
is_closed: false,
is_hidden: false,
- supported_kinds: Some(vec![78, 30078]),
+ supported_kinds: Some(vec![78, 30078, KIND_FARM_FILE_METADATA]),
}
}
@@ -832,6 +839,13 @@ mod tests {
serde_json::from_str(&json).expect("tags")
}
+ fn has_tag(tags: &[Vec<String>], key: &str, value: &str) -> bool {
+ tags.iter().any(|tag| {
+ tag.first().map(|entry| entry.as_str()) == Some(key)
+ && tag.get(1).map(|entry| entry.as_str()) == Some(value)
+ })
+ }
+
#[test]
fn bindings_reject_invalid_json() {
let bindings: [fn(&str) -> Result<String, RadrootsJsValue>; 46] = [
@@ -844,7 +858,7 @@ mod tests {
calendar_date_event_tags,
calendar_time_event_tags,
calendar_tags,
- calendar_rsvp_tags,
+ calendar_event_rsvp_tags,
repost_tags,
generic_repost_tags,
report_tags,
@@ -863,9 +877,9 @@ mod tests {
message_file_tags,
seal_tags,
gift_wrap_tags,
- farm_workspace_tags,
- farm_crdt_tags,
- farm_file_tags,
+ farm_workspace_manifest_tags,
+ farm_crdt_change_tags,
+ farm_file_metadata_tags,
relay_auth_tags,
http_auth_tags,
group_put_user_tags,
@@ -921,13 +935,14 @@ mod tests {
assert_tags_json(calendar_date_event_tags(
&serde_json::to_string(&sample_calendar_date_event()).expect("date json"),
));
- assert_tags_json(calendar_time_event_tags(
+ let time_tags = tags_json(calendar_time_event_tags(
&serde_json::to_string(&sample_calendar_time_event()).expect("time json"),
));
+ assert!(has_tag(&time_tags, "D", "2026-06-20"));
assert_tags_json(calendar_tags(
&serde_json::to_string(&sample_calendar()).expect("calendar json"),
));
- assert_tags_json(calendar_rsvp_tags(
+ assert_tags_json(calendar_event_rsvp_tags(
&serde_json::to_string(&sample_calendar_rsvp()).expect("rsvp json"),
));
assert_tags_json(reaction_tags(
@@ -964,7 +979,9 @@ mod tests {
let mut rsvp = sample_calendar_rsvp();
rsvp.event = event_target(31923, 'f');
- assert!(calendar_rsvp_tags(&serde_json::to_string(&rsvp).expect("rsvp json")).is_err());
+ assert!(
+ calendar_event_rsvp_tags(&serde_json::to_string(&rsvp).expect("rsvp json")).is_err()
+ );
let mut report = sample_report();
report.reported_pubkey.clear();
@@ -975,17 +992,17 @@ mod tests {
fn field_bindings_encode_to_json_when_input_is_valid() {
let workspace_json =
serde_json::to_string(&sample_workspace_manifest()).expect("workspace json");
- assert_tags_json(farm_workspace_tags(&workspace_json));
+ assert_tags_json(farm_workspace_manifest_tags(&workspace_json));
let crdt_json = serde_json::json!({
"change": sample_crdt_change(),
"author_pubkey": "author_pubkey"
})
.to_string();
- assert_tags_json(farm_crdt_tags(&crdt_json));
+ assert_tags_json(farm_crdt_change_tags(&crdt_json));
let file_json = serde_json::to_string(&sample_file_metadata()).expect("file json");
- assert_tags_json(farm_file_tags(&file_json));
+ assert_tags_json(farm_file_metadata_tags(&file_json));
let relay_auth_json = serde_json::to_string(&RadrootsRelayAuth {
relay: "wss://relay.example.invalid/farm/field-group".to_string(),
@@ -1091,7 +1108,8 @@ mod tests {
assert!(metadata_tags.contains(&vec![
"supported_kinds".to_string(),
"78".to_string(),
- "30078".to_string()
+ "30078".to_string(),
+ KIND_FARM_FILE_METADATA.to_string()
]));
assert_tags_json(group_admins_tags(
&serde_json::to_string(&RadrootsGroupAdmins {
diff --git a/spec/social-events.md b/spec/social-events.md
@@ -116,6 +116,14 @@ helpers, and conformance vectors exist. Production-v1 repost, report, calendar c
behavior remains substrate-visible by default unless a consumer proves that it should be promoted
into the curated operation surface.
+`radroots_events_codec_wasm` exposes the canonical JSON-to-tags helper names `post_tags`,
+`comment_tags`, `reaction_tags`, `article_tags`, `file_metadata_tags`,
+`calendar_date_event_tags`, `calendar_time_event_tags`, `calendar_tags`,
+`calendar_event_rsvp_tags`, `repost_tags`, `generic_repost_tags`, and `report_tags` for the public
+social substrate. The same wasm crate exposes `farm_workspace_manifest_tags`,
+`farm_crdt_change_tags`, `farm_file_metadata_tags`, `relay_auth_tags`, and `http_auth_tags` for the
+field event substrate.
+
## Conformance Boundary
Every new social codec and every upgraded existing social codec must have deterministic valid and