use super::domain::{Projection, strict_value};
use super::*;
use crate::sync::wire::ChangeWire;
use serde_json::json;
pub(super) fn authority() -> Authority {
fixture_authority()
}
pub(super) fn change() -> ChangeWire {
ChangeWire {
change_id: "AAAAAAAAAAAAAAAA".into(),
client_id: "origin".into(),
local_seq: 1,
entity_type: "task".into(),
entity_id: "BBBBBBBBBBBBBBBB".into(),
field: Some("deleted".into()),
op_type: "set_field".into(),
payload: json!({"workspace_id":"0000000000000000","workspace_key":"default","value":"1"}),
base_version: Some("CCCCCCCCCCCCCCCC".into()),
created_at: "2026-09-22T00:00:00Z".into(),
server_seq: None,
}
}
#[test]
fn exact_envelope_randomness_tamper_truncation_and_context() {
let a = authority();
let c = change();
let record = codec::seal(&a, &c).unwrap();
assert!(crate::sync::persistence::changes::canonical_equal(
&c,
&codec::open(&a, &record).unwrap()
));
assert_ne!(record, codec::seal(&a, &c).unwrap());
for n in 0..record.len() {
assert!(codec::open(&a, &record[..n]).is_err());
}
for n in 0..record.len() {
let mut bad = record.clone();
bad[n] ^= 1;
assert!(codec::open(&a, &bad).is_err());
}
let mut wrong = authority();
wrong.context.stream = [9; 32];
assert!(codec::open(&wrong, &record).is_err());
let mut trailing = record.clone();
trailing.push(0);
assert!(codec::open(&a, &trailing).is_err());
assert_eq!(record.len(), serde_json::to_vec(&c).unwrap().len() + 296);
}
#[test]
fn strict_json_and_numeric_equality() {
for input in [
r#"{"a":1,"a":2}"#,
r#"{"p":{"value":1,"\u0076alue":1}}"#,
"18446744073709551616",
"-9223372036854775809",
"1e999",
"[] x",
] {
assert!(strict_value(input.as_bytes()).is_err(), "{input}");
}
assert_eq!(
strict_value(b"18446744073709551615").unwrap(),
json!(u64::MAX)
);
assert_eq!(
strict_value(b"-9223372036854775808").unwrap(),
json!(i64::MIN)
);
assert_ne!(strict_value(b"1").unwrap(), strict_value(b"1.0").unwrap());
assert_eq!(strict_value(b"1.0").unwrap(), strict_value(b"1e0").unwrap());
assert_eq!(strict_value(b"-0").unwrap(), strict_value(b"0.0").unwrap());
for depth in [64, 65] {
let s = format!("{}0{}", "[".repeat(depth), "]".repeat(depth));
assert_eq!(strict_value(s.as_bytes()).is_ok(), depth == 64);
}
let mut value = serde_json::to_value(change()).unwrap();
value.as_object_mut().unwrap().remove("server_seq");
assert!(domain::decode(&serde_json::to_vec(&value).unwrap()).is_err());
}
#[test]
fn member_local_seq_cannot_push_peer_sequences_to_overflow() {
let mut c = change();
c.local_seq = crate::sync::wire::MAX_LOCAL_SEQ;
assert!(domain::decode(&serde_json::to_vec(&c).unwrap()).is_ok());
for local_seq in [crate::sync::wire::MAX_LOCAL_SEQ + 1, i64::MAX, -1] {
c.local_seq = local_seq;
assert!(domain::decode(&serde_json::to_vec(&c).unwrap()).is_err());
}
}
#[test]
fn parent_projection_limits_and_domain_binding() {
for action in 0..=2 {
let p = Projection::Parent {
action: crate::sync::persistence::parent_liveness::ParentAction::from_byte(action)
.unwrap(),
workspace: "w".repeat(256),
task: "t".repeat(256),
deleted: false,
version: Some("v".repeat(256)),
};
let bytes = p.encode();
assert_eq!(bytes.len(), 784);
assert!(Projection::decode(&bytes).unwrap() == p);
}
let mut c = change();
let p = domain::validate(&c).unwrap();
assert!(
p == Projection::Parent {
action: crate::sync::persistence::parent_liveness::ParentAction::Set,
workspace: "0000000000000000".into(),
task: c.entity_id.clone(),
deleted: true,
version: c.base_version.clone()
}
);
c.op_type = "resolve_field".into();
c.base_version = None;
assert!(matches!(
domain::validate(&c).unwrap(),
Projection::Parent {
action: crate::sync::persistence::parent_liveness::ParentAction::ForceResolve,
version: None,
..
}
));
c.payload["series_id"] = json!("x");
assert!(domain::validate(&c).is_err());
}
#[test]
fn administration_operations_keep_strict_shapes_and_workspace_scope() {
let admin = |op: &str, entity_type: &str, entity: &str, field: Option<&str>, payload| {
let mut c = change();
c.op_type = op.into();
c.entity_type = entity_type.into();
c.entity_id = entity.into();
c.field = field.map(Into::into);
c.base_version = None;
c.payload = payload;
c
};
let ws = json!({"workspace_id": "0000000000000000", "workspace_key": "default"});
let with = |extra: serde_json::Value| {
let mut p = ws.clone();
p.as_object_mut()
.unwrap()
.extend(extra.as_object().unwrap().clone());
p
};
let t = "2026-09-22T00:00:00Z";
let valid = [
admin(
"set_project_metadata",
"project",
"PPPPPPPPPPPPPPPP",
None,
with(json!({"key": "core", "name": "Core", "prefix": "CORE", "updated_at": t})),
),
admin(
"project_delete",
"project",
"PPPPPPPPPPPPPPPP",
None,
with(json!({"deleted_at": t})),
),
admin(
"set_label_name",
"label",
"old",
None,
with(json!({"name": "old", "new_name": "new", "renamed_at": t})),
),
admin(
"label_delete",
"label",
"old",
None,
with(json!({"name": "old", "deleted_at": t})),
),
admin(
"label_restore",
"label",
"old",
None,
with(
json!({"name": "old", "created_at": t, "task_ids": ["BBBBBBBBBBBBBBBB"],
"series_ids": [], "restored_at": t}),
),
),
admin(
"create_workspace",
"workspace",
"WWWWWWWWWWWWWWWW",
None,
json!({"key": "lab", "name": "Lab", "created_at": t}),
),
admin(
"set_workspace_field",
"workspace",
"WWWWWWWWWWWWWWWW",
Some("name"),
json!({"value": "Lab"}),
),
];
for c in &valid {
assert!(
domain::validate(c).unwrap() == Projection::None,
"{}",
c.op_type
);
let bytes = serde_json::to_vec(c).unwrap();
assert!(crate::sync::persistence::changes::canonical_equal(
c,
&domain::decode(&bytes).unwrap()
));
}
let mut rejected = Vec::new();
for c in &valid {
let mut extra = c.clone();
extra.payload["unexpected"] = json!(1);
let mut versioned = c.clone();
versioned.base_version = Some("CCCCCCCCCCCCCCCC".into());
let mut fielded = c.clone();
fielded.field = if c.field.is_some() {
None
} else {
Some("name".into())
};
rejected.extend([extra, versioned, fielded]);
let mut unscoped = c.clone();
if c.entity_type == "workspace" {
unscoped.payload["workspace_id"] = json!("0000000000000000");
} else {
unscoped
.payload
.as_object_mut()
.unwrap()
.remove("workspace_id");
}
rejected.push(unscoped);
}
let mut same_name = valid[2].clone();
same_name.payload["new_name"] = json!("old");
let mut mismatched = valid[3].clone();
mismatched.entity_id = "other".into();
let mut workspace_field = valid[6].clone();
workspace_field.field = Some("deleted".into());
let mut workspace_id = valid[5].clone();
workspace_id.entity_id = "not a workspace".into();
let mut restore_ids = valid[4].clone();
restore_ids.payload["task_ids"] = json!([1]);
let mut unknown = valid[1].clone();
unknown.op_type = "project_restore".into();
rejected.extend([
same_name,
mismatched,
workspace_field,
workspace_id,
restore_ids,
unknown,
]);
for c in rejected {
assert!(domain::validate(&c).is_err(), "{c:?}");
}
}
#[test]
fn device_labels_are_encrypted_unscoped_records() {
let mut label = change();
label.entity_type = "device".into();
label.entity_id = "ab".repeat(32);
label.field = None;
label.op_type = "publish_device_label".into();
label.payload = json!({"label":"Office Mac"});
label.base_version = None;
assert!(matches!(
domain::validate(&label).unwrap(),
Projection::None
));
label.payload["label"] = json!("bad\nname");
assert!(domain::validate(&label).is_err());
label.payload = json!({"label":"Office Mac", "extra":true});
assert!(domain::validate(&label).is_err());
}
#[test]
fn every_registered_operation_name_has_encrypted_validation() {
for op in crate::change_log::op_type::ALL {
assert!(
domain::payload_keys(op).is_some(),
"{op} lacks encrypted validation"
);
}
assert!(domain::payload_keys("unregistered_operation").is_none());
}