ghostlight import-key: pin whole-record NFC and the admit_resolved duplicate backstop
Tests only, no production change. Both build. A late NFD sequence and a late format character in a long lore-shaped path kill an is_nfc-on-prefix mutant; a resolved effect carrying two subjects with one key kills a fresh declared set in admit_resolved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ee174c68ce
commit
4126c83eff
1 changed files with 41 additions and 0 deletions
|
|
@ -580,6 +580,9 @@ fn a_record_key_is_one_canonical_spelling() {
|
|||
"Del\u{a0}ta",
|
||||
"Del\u{2003}ta",
|
||||
"Del\nta",
|
||||
// The violation sits deep in a long, real-shaped path, past any prefix.
|
||||
"Worldbuilding/Pre-Elysium/Factions/Powers/Minor/Cafe\u{301}",
|
||||
"Worldbuilding/Pre-Elysium/Factions/Powers/Minor/Ewan\u{200b}Hart",
|
||||
];
|
||||
for (index, record) in refused.iter().enumerate() {
|
||||
let set = rejected(submit(&mut kernel, "bad", record));
|
||||
|
|
@ -660,3 +663,41 @@ fn a_loaded_state_with_a_bad_import_key_is_refused() {
|
|||
"a key with a format character must not load"
|
||||
);
|
||||
}
|
||||
|
||||
/// The admission backstop, reached with an effect resolution never produced: a
|
||||
/// resolved patch whose two subjects carry one key. The control is the same
|
||||
/// effect with distinct keys, admitted by the same function.
|
||||
#[test]
|
||||
fn admitting_a_resolved_effect_refuses_two_subjects_with_one_key() {
|
||||
let (_dir, kernel) = keyed_world();
|
||||
let place = commons(&kernel);
|
||||
let resolve = || {
|
||||
crate::patch::resolve_patch(
|
||||
&kernel.state,
|
||||
CommandId::new(),
|
||||
&patch_of(vec![
|
||||
mirror("first", Some(key("aetheria.ship", "Beta")), place),
|
||||
mirror("second", Some(key("aetheria.ship", "Gamma")), place),
|
||||
]),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("two distinct keys resolve")
|
||||
};
|
||||
let resolves_to = crate::resolution_revision(&kernel.state).unwrap();
|
||||
let mut control = kernel.state.clone();
|
||||
crate::admit_resolved(&mut control, &resolve(), resolves_to)
|
||||
.expect("distinct keys are admitted");
|
||||
|
||||
let mut twinned = resolve();
|
||||
assert_eq!(twinned.subjects.len(), 2);
|
||||
twinned.subjects[1].subject.import_key = twinned.subjects[0].subject.import_key.clone();
|
||||
let mut state = kernel.state.clone();
|
||||
let error = crate::admit_resolved(&mut state, &twinned, resolves_to)
|
||||
.expect_err("one key on two resolved subjects is refused");
|
||||
assert!(
|
||||
matches!(&error, KernelError::Invariant(why) if why.contains("import key")),
|
||||
"{error:?}"
|
||||
);
|
||||
assert!(!format!("{error:?}").contains("Beta"), "the refusal echoed the key");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue