The cardname is the the card's key in the Packs, and it has several related components. We will use the attribute_accessor :key whether on a card or a cardname (implicitely the card proxies to the cardname on any of these related attributes). The key is necessary as a card table index field, so it must behave as a key in terms of uniqueness. If two different cardnames map to the same key, they are the same cardname even if the names are different. Each card also has a "canonical name" as defined by the name field in the database and cache (the persistant name). Internationalization and multi-lingual Wagns may also impact here. Each language may have unique key mapping algorithms, and both the name and content fields
Cardnames are segmented paths in the card namespace, and the plus sign '+' is the path separator just like '/' or '\' is the same thing in most file system or URI paths. A simple name is one without a plus, and the empty string is not a name, so if it doesn't already '++' should go to just '+' in translations to keys.
Cardnames are actually very similar to pathnames in many ways, so much so that we could represent cards in a filesystem where each card is a subdirectory containing a file (content) and an implicite symlink (to the directory with the Cardtype card). Track the changes to content and links with a source code tracking system and you can represent the wagn with all of its history.
Translation to key and codename can be implemented in various ways, but however you implement it has to be true that you can translate the simple name segments to key or codename and back and join them back together and you must get the same result as translating the whole thing or any sub-parts.
In directory terms, the "trunk" of a card is like the parent directory (..) and the "tag" is an entry in the parrent directory (and always a "simple" name). The tags as independent entities exist in the global namespace, so we add the separator for relative names (+tagname) which is how we are different than filesystem paths where relative (local) paths are the default, and you have to add / for a global path.