Repository navigation
Description
Problem
Petnames::open (pkgs/id/crates/id-core/src/petname.rs:59) replays petnames.jsonl through apply (petname.rs:196-209), which inserts each Record::Set name verbatim. The write path, Petnames::set (petname.rs:128-163), refuses:
- names that fail
normalize_name— empty, longer than 64 chars, or containing control/format (Cf) characters (petname.rs:262-278); - a name whose
foldequals another contact's petname for the same owner (Conflict); - a name whose UTS Bump checkmarx/ast-github-action from 2.0.19 to 2.0.20 #39
skeletonmatches another contact's petname or a directory-alleged account name (the anti-mimicry guard the module doc states as its purpose: "the store refuses a petname that could be taken for someone else's name").
None of those invariants are re-checked at load. A journal written by an older build, a hand edit, a partial restore, or another writer therefore loads state the store itself would never create: two contacts of one owner holding fold-equal petnames (PayPal / paypal), a petname carrying U+200B, or an 80-char name — and the display/labels path consumes them as if they had passed the guards.
Evidence (verified this run, origin/main a51be0e)
Probe test on the laptop (worktree of origin/main, cargo test -p id-core --test probe_petname_load): a hand-written journal with four set records — fold-duplicate names for two accounts, a name containing U+200B, and an 80-char name — loads with all four records present verbatim; Petnames::open returns Ok.
This is the same shape as #5179 / PR #5190, where Registry::load for publications was fixed to validate persisted records against publish() invariants at load. The petname store was not covered by that fix. Related audits: #2898 Phase 3 and #4001 both name "directory/petname persistence restores" in their closing-inventory scope — this issue is the concrete, reproduced instance for the petname store and can serve as that inventory's named follow-up for this seam.
Note the deliberate legacy tolerance in the comparison paths (fold/skeleton strip Cf "so a name stored with one (before they were refused) cannot spoof by the comparison path", petname.rs:236-243): the fix must disposition legacy stored names explicitly — fail-loud like the publications registry, quarantine-with-warning, or normalise — rather than silently breaking existing journals.
Acceptance criteria
-
Petnames::opendispositions every replayedSetrecord against theset()invariants (normalisability, per-owner fold uniqueness, per-owner skeleton uniqueness), with the chosen behaviour for violations (error naming the line / skip-with-warning / normalise) stated in the module doc. - The alleged-name skeleton check that needs directory state is either applied where the directory is available at open time or explicitly documented as a load-time exemption with the reason.
- Tests: journal with fold-duplicate names, a Cf-carrying name, and an overlong name each produce the documented disposition; a journal written by current
set()calls reopens unchanged. - Existing petname tests stay green (laptop or CI).
🤖 Filed by new-issue-creator-code-a (lane A), 2026-11-03.
Activity
dezren39 commentedon Nov 4, 2026
🤖 Agent note · filed