[Backend] A character's name is not checked against other characters' existing heard-as aliases #634

Closed
opened 2026-09-12 22:22:06 +00:00 by claude-bot · 2 comments
Collaborator

Found while doing #580, and deliberately left out of that PR because it is pre-existing and reachable without an import.

campaign_character_service._reject_alias_collisions checks in one direction only: the new character's aliases against other characters' names. Nothing checks the new character's name against other characters' existing aliases.

So this sequence is accepted today, no import involved:

  1. Create character Idani with heard_as: ["Wyatt"] — allowed, because no character called Wyatt exists yet.
  2. Create character Wyatt — allowed, because the check never looks at Idani's aliases.

The campaign now holds exactly the state the collision rule exists to prevent, and the alias map built from those rows will rewrite every "Wyatt" in the transcript to "Idani" — including the beat evidence that decides whether a beat about Wyatt is supported. The docstring's own words for why that matters: "a feature that quietly renames one player's character to another's is worse than the misspelling it was fixing."

Why it is not part of #580. That change made stubs carry aliases, so it added the import route into a similar state; #580 closed that by having the check also consult unclaimed unlinked_members character names. This one is the reverse direction and predates both — the ordering above needs no export, no import and no stub.

Expected. Creating or renaming a character whose name matches another character's heard_as entry is refused with the same shape of message the alias direction gives. Worth checking both create and update paths, and deciding what to do about campaigns already in that state — most likely nothing automatic, but the GM should be able to see it.

Acceptance:

  • _reject_alias_collisions (or its caller) refuses a character name that collides with another character's alias, on create and on rename.
  • A test for the two-step ordering above, which passes today and should not.
  • Decide and document what happens to an existing campaign that already holds the collision — the alias map is built at transcription time, so it is silently active until someone looks.

Related: #579 (the aliases), #580 (carrying them through export/import, which added the stub-name half of this check).

Found while doing #580, and deliberately left out of that PR because it is pre-existing and reachable without an import. `campaign_character_service._reject_alias_collisions` checks in one direction only: **the new character's aliases** against other characters' names. Nothing checks **the new character's name** against other characters' existing aliases. So this sequence is accepted today, no import involved: 1. Create character *Idani* with `heard_as: ["Wyatt"]` — allowed, because no character called Wyatt exists yet. 2. Create character *Wyatt* — allowed, because the check never looks at Idani's aliases. The campaign now holds exactly the state the collision rule exists to prevent, and the alias map built from those rows will rewrite every "Wyatt" in the transcript to "Idani" — including the beat evidence that decides whether a beat about Wyatt is supported. The docstring's own words for why that matters: *"a feature that quietly renames one player's character to another's is worse than the misspelling it was fixing."* **Why it is not part of #580.** That change made stubs carry aliases, so it added the *import* route into a similar state; #580 closed that by having the check also consult unclaimed `unlinked_members` character names. This one is the reverse direction and predates both — the ordering above needs no export, no import and no stub. **Expected.** Creating or renaming a character whose name matches another character's `heard_as` entry is refused with the same shape of message the alias direction gives. Worth checking both create and update paths, and deciding what to do about campaigns already in that state — most likely nothing automatic, but the GM should be able to see it. **Acceptance:** - [ ] `_reject_alias_collisions` (or its caller) refuses a character name that collides with another character's alias, on create and on rename. - [ ] A test for the two-step ordering above, which passes today and should not. - [ ] Decide and document what happens to an existing campaign that already holds the collision — the alias map is built at transcription time, so it is silently active until someone looks. Related: #579 (the aliases), #580 (carrying them through export/import, which added the stub-name half of this check).
Author
Collaborator

Picking this up (2 October). Branch fix/634-name-vs-alias-collision: the name check gets the missing direction on every path that sets a character's name, with the same comparison and refusal style as the existing alias check, and import follows whatever import already does for the existing direction.

Picking this up (2 October). Branch `fix/634-name-vs-alias-collision`: the name check gets the missing direction on every path that sets a character's name, with the same comparison and refusal style as the existing alias check, and import follows whatever import already does for the existing direction.
Author
Collaborator

Done in PR #1034, merged to main on 2026-10-02 once CI was green on a head carrying main. Its earlier runs went red only on two flaky frontend tests (fixed in #1040 and #1041); the change itself is backend only.

A new or renamed character is now refused when its name is already listed as another character's misspelling ("heard as") in the same campaign, on every path that names a character (400 or 422 by route). As the PR explains, the existing state never rewrote transcripts: build_alias_map already drops such an alias, so the real harm was a misspelling that silently stopped being corrected. Campaigns already in that state need nothing done. No migration, and no bot contract change.

Done in PR #1034, merged to main on 2026-10-02 once CI was green on a head carrying main. Its earlier runs went red only on two flaky frontend tests (fixed in #1040 and #1041); the change itself is backend only. A new or renamed character is now refused when its name is already listed as another character's misspelling ("heard as") in the same campaign, on every path that names a character (400 or 422 by route). As the PR explains, the existing state never rewrote transcripts: `build_alias_map` already drops such an alias, so the real harm was a misspelling that silently stopped being corrected. Campaigns already in that state need nothing done. No migration, and no bot contract change.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#634
No description provided.