Enhance redaction handling and update snapshot references

- Added support for redacting tagged values in the `RedactionMap` implementation, ensuring that nested tagged values are processed correctly.
- Updated multiple snapshot files to replace specific reference IDs with deterministic `id-N` values, improving consistency across tests and snapshots.
- Refactored internment logic in `internable.rs` to include variant references, ensuring proper redaction of property values in snapshots.
This commit is contained in:
Joe 2026-02-06 19:20:16 -06:00
parent 2978dee70d
commit 5442c02f67
11 changed files with 53 additions and 33 deletions

View file

@ -79,6 +79,9 @@ impl RedactionMap {
*mapping = new_map; *mapping = new_map;
} }
Value::Tagged(tagged) => {
self.redact(&mut tagged.value);
}
_ => {} _ => {}
} }
} }

View file

@ -38,7 +38,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 9893f640faccb9150197026b0ca91712 "!Ref": id-5
id-5: id-5:
Children: [] Children: []
ClassName: MeshPart ClassName: MeshPart

View file

@ -15,7 +15,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": a014b12bf90014847f564374c73a5f38 "!Ref": id-9
id-11: id-11:
Children: [] Children: []
ClassName: Model ClassName: Model
@ -30,7 +30,7 @@ instances:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": a014b12bf90014847f564374c73a5f38 "!Ref": id-9
id-2: id-2:
Children: Children:
- id-3 - id-3
@ -68,7 +68,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 4d3455270f6618409e7d40dbcad9e25b "!Ref": id-5
id-5: id-5:
Children: Children:
- id-6 - id-6
@ -91,7 +91,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 4d3455270f6618409e7d40dbcad9e25b "!Ref": id-5
id-7: id-7:
Children: Children:
- id-8 - id-8
@ -119,7 +119,7 @@ instances:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": 4536e7ddde75409951458987be6ccfb5 "!Ref": id-7
id-9: id-9:
Children: Children:
- id-10 - id-10

View file

@ -15,7 +15,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": a014b12bf90014847f564374c73a5f38 "!Ref": id-9
id-2: id-2:
Children: Children:
- id-3 - id-3
@ -53,7 +53,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 4d3455270f6618409e7d40dbcad9e25b "!Ref": id-5
id-5: id-5:
Children: Children:
- id-6 - id-6
@ -76,7 +76,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 4d3455270f6618409e7d40dbcad9e25b "!Ref": id-5
id-7: id-7:
Children: Children:
- id-8 - id-8
@ -101,7 +101,7 @@ instances:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": 4536e7ddde75409951458987be6ccfb5 "!Ref": id-7
id-9: id-9:
Children: Children:
- id-10 - id-10

View file

@ -15,7 +15,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": a2c2197b7d6e19e64b8991926744f3a6 "!Ref": id-9
id-2: id-2:
Children: Children:
- id-3 - id-3
@ -53,7 +53,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 75d2ce9353a6c62f29130f18c35c89ce "!Ref": id-5
id-5: id-5:
Children: Children:
- id-6 - id-6
@ -76,7 +76,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 75d2ce9353a6c62f29130f18c35c89ce "!Ref": id-5
id-7: id-7:
Children: Children:
- id-8 - id-8
@ -101,7 +101,7 @@ instances:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": 103b2053eb8c4ea0a65500d5c20bd84f "!Ref": id-7
Scale: Scale:
"!Float32": 1 "!Float32": 1
id-9: id-9:

View file

@ -15,7 +15,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": a2c2197b7d6e19e64b8991926744f3a6 "!Ref": id-9
id-2: id-2:
Children: Children:
- id-3 - id-3
@ -53,7 +53,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 75d2ce9353a6c62f29130f18c35c89ce "!Ref": id-5
id-5: id-5:
Children: Children:
- id-6 - id-6
@ -76,7 +76,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": 75d2ce9353a6c62f29130f18c35c89ce "!Ref": id-5
id-7: id-7:
Children: Children:
- id-8 - id-8
@ -101,7 +101,7 @@ instances:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": 103b2053eb8c4ea0a65500d5c20bd84f "!Ref": id-7
id-9: id-9:
Children: Children:
- id-10 - id-10

View file

@ -25,6 +25,6 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": ca113df936e8659c00936176b40b02ae "!Ref": id-4
messageCursor: 1 messageCursor: 1
sessionId: id-1 sessionId: id-1

View file

@ -26,7 +26,7 @@ instances:
Attributes: Attributes:
"!Attributes": {} "!Attributes": {}
Value: Value:
"!Ref": ca113df936e8659c00936176b40b02ae "!Ref": id-4
id-4: id-4:
Children: [] Children: []
ClassName: ObjectValue ClassName: ObjectValue

View file

@ -20,7 +20,7 @@ body:
NeedsPivotMigration: NeedsPivotMigration:
"!Bool": false "!Bool": false
PrimaryPart: PrimaryPart:
"!Ref": a014b12bf90014847f564374c73a5f38 "!Ref": id-9
removed: [] removed: []
updated: updated:
- changedClassName: ~ - changedClassName: ~

View file

@ -124,9 +124,7 @@ fn fetch_experience_name(place_id: u64) -> anyhow::Result<String> {
let client = Client::new(); let client = Client::new();
// Place ID -> Universe ID // Place ID -> Universe ID
let universe_url = format!( let universe_url = format!("https://apis.roblox.com/universes/v1/places/{place_id}/universe");
"https://apis.roblox.com/universes/v1/places/{place_id}/universe"
);
let universe: UniverseResponse = client let universe: UniverseResponse = client
.get(&universe_url) .get(&universe_url)
.send() .send()
@ -203,18 +201,12 @@ mod tests {
#[test] #[test]
fn sanitize_brackets_and_parens() { fn sanitize_brackets_and_parens() {
assert_eq!( assert_eq!(sanitize_name("My Game (UPDATE) [v2.0]"), "my-game");
sanitize_name("My Game (UPDATE) [v2.0]"),
"my-game"
);
} }
#[test] #[test]
fn sanitize_emojis() { fn sanitize_emojis() {
assert_eq!( assert_eq!(sanitize_name("Cool Game 🌊🏃⚡"), "cool-game");
sanitize_name("Cool Game 🌊🏃⚡"),
"cool-game"
);
} }
#[test] #[test]

View file

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use rbx_dom_weak::types::Ref; use rbx_dom_weak::types::{Ref, Variant};
use serde::Serialize; use serde::Serialize;
use librojo::web_api::{ use librojo::web_api::{
@ -38,6 +38,7 @@ impl Internable<Ref> for ReadResponse<'_> {
redactions.intern(root_id); redactions.intern(root_id);
let root_instance = self.instances.get(&root_id).unwrap(); let root_instance = self.instances.get(&root_id).unwrap();
intern_variant_refs(redactions, root_instance.properties.values().map(|v| v.as_ref()));
for &child_id in root_instance.children.iter() { for &child_id in root_instance.children.iter() {
self.intern(redactions, child_id); self.intern(redactions, child_id);
@ -49,6 +50,8 @@ impl<'a> Internable<&'a HashMap<Ref, Instance<'_>>> for Instance<'a> {
fn intern(&self, redactions: &mut RedactionMap, other_instances: &HashMap<Ref, Instance<'_>>) { fn intern(&self, redactions: &mut RedactionMap, other_instances: &HashMap<Ref, Instance<'_>>) {
redactions.intern(self.id); redactions.intern(self.id);
intern_variant_refs(redactions, self.properties.values().map(|v| v.as_ref()));
for child_id in self.children.iter() { for child_id in self.children.iter() {
let child = &other_instances[child_id]; let child = &other_instances[child_id];
child.intern(redactions, other_instances); child.intern(redactions, other_instances);
@ -77,6 +80,13 @@ impl Internable<()> for MessagesPacket<'_> {
fn intern_instance_updates(redactions: &mut RedactionMap, updates: &[InstanceUpdate]) { fn intern_instance_updates(redactions: &mut RedactionMap, updates: &[InstanceUpdate]) {
for update in updates { for update in updates {
redactions.intern(update.id); redactions.intern(update.id);
intern_variant_refs(
redactions,
update
.changed_properties
.values()
.filter_map(|v| v.as_ref()),
);
} }
} }
@ -109,3 +119,18 @@ fn intern_instance_additions(
additions[root_id].intern(redactions, additions); additions[root_id].intern(redactions, additions);
} }
} }
/// Scan property values for Ref variants and intern them so they get redacted
/// to deterministic `id-N` values in snapshots.
fn intern_variant_refs<'a>(
redactions: &mut RedactionMap,
properties: impl Iterator<Item = &'a Variant>,
) {
for variant in properties {
if let Variant::Ref(r) = variant {
if !r.is_none() {
redactions.intern(*r);
}
}
}
}