chat: document connections.simplex_name as transient carrier

Audit flagged the column as "INSERTed but never UPDATEd". This is by
design per the prior plan's connect-via-plan flow: the column is a
transient carrier between connection-creation and contact-creation.
After the Contact row is created via XInfo handling, contacts.simplex_name
is the source of truth and the connections value is a historical snapshot.
Documents the intent so future readers don't reflag it.
This commit is contained in:
shum
2026-06-05 16:40:20 +00:00
parent c1235c01bb
commit b1d18100f4
4 changed files with 35 additions and 0 deletions
+4
View File
@@ -2957,6 +2957,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
conn' <- updatePeerChatVRange activeConn chatVRange
case chatMsgEvent of
XInfo p -> do
-- Consume the transient simplex_name carrier from the connection row
-- (set in createConnection_ on the connect-via-plan path) and pass it
-- to createDirectContact; after this point contacts.simplex_name is
-- the source of truth.
let Connection {simplexName} = conn'
Profile {simplexName = pSimplexName} = p
(ct, displaced_) <- withStore $ \db -> createDirectContact db vr user conn' p simplexName
@@ -6,6 +6,17 @@ module Simplex.Chat.Store.Postgres.Migrations.M20260603_simplex_name where
import Data.Text (Text)
import Text.RawString.QQ (r)
-- contacts.simplex_name and groups.simplex_name are the source of truth for the
-- entity's current name (updated when XInfo/XGrpInfo arrives).
--
-- connections.simplex_name is a TRANSIENT carrier for the connect-via-plan
-- (connect-by-name) path: when the user initiates a connection by typing
-- #name.simplex, the peer's profile is not yet available, so the name is
-- stashed on the connection row. When XInfo arrives and the Contact row is
-- created, the XInfo handler in Library/Subscriber.hs reads
-- connections.simplex_name and passes it to createDirectContact. After contact
-- creation, contacts.simplex_name is canonical and the connection's value
-- becomes a historical snapshot - it is intentionally never UPDATEd.
m20260603_simplex_name :: Text
m20260603_simplex_name =
[r|
@@ -5,6 +5,17 @@ module Simplex.Chat.Store.SQLite.Migrations.M20260603_simplex_name where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-- contacts.simplex_name and groups.simplex_name are the source of truth for the
-- entity's current name (updated when XInfo/XGrpInfo arrives).
--
-- connections.simplex_name is a TRANSIENT carrier for the connect-via-plan
-- (connect-by-name) path: when the user initiates a connection by typing
-- #name.simplex, the peer's profile is not yet available, so the name is
-- stashed on the connection row. When XInfo arrives and the Contact row is
-- created, the XInfo handler in Library/Subscriber.hs reads
-- connections.simplex_name and passes it to createDirectContact. After contact
-- creation, contacts.simplex_name is canonical and the connection's value
-- becomes a historical snapshot - it is intentionally never UPDATEd.
m20260603_simplex_name :: Query
m20260603_simplex_name =
[sql|
+9
View File
@@ -277,6 +277,15 @@ toMaybeConnection vr ((Just connId, Just agentConnId, Just connLevel, viaContact
Just $ toConnection vr ((connId, agentConnId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, xContactId) :. (customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled_, pqRcvEnabled_, authErrCounter, quotaErrCounter, connChatVersion, minVer, maxVer) :. Only simplexNameRaw)
toMaybeConnection _ _ = Nothing
-- | Creates a new connection row. The @simplexName@ argument is a TRANSIENT
-- carrier for the connect-via-plan (connect-by-name) path: when the user
-- initiates a connection by typing #name.simplex, the peer's profile is not
-- yet available. The name is stashed on connections.simplex_name so that, when
-- XInfo arrives and the Contact row is created, the XInfo handler in
-- Library/Subscriber.hs (saveConnInfo) can read it and pass it to
-- createDirectContact. After contact creation, contacts.simplex_name is the
-- source of truth and the connection's value becomes a historical snapshot
-- that is intentionally never updated.
createConnection_ :: DB.Connection -> UserId -> ConnType -> Maybe Int64 -> ConnId -> ConnStatus -> VersionChat -> VersionRangeChat -> Maybe ContactId -> Maybe Int64 -> Maybe ProfileId -> Int -> UTCTime -> SubscriptionMode -> PQSupport -> Maybe SimplexNameInfo -> IO Connection
createConnection_ db userId connType entityId acId connStatus connChatVersion peerChatVRange@(VersionRange minV maxV) viaContact viaUserContactLink customUserProfileId connLevel currentTs subMode pqSup simplexName = do
viaLinkGroupId :: Maybe Int64 <- fmap join . forM viaUserContactLink $ \ucLinkId ->