From 5ce9e852a30b4b7cc3c15977d5e5f5e0e4526320 Mon Sep 17 00:00:00 2001 From: shum Date: Mon, 8 Jun 2026 11:49:07 +0000 Subject: [PATCH] deps: bump simplexmq for HTTP resolver; adapt NameRecord consumers simplexmq 92b3d049 reshaped NameRecord text fields from Maybe Text to Text (empty string sentinel). Adapt firstNameLink to take Text directly and treat T.null as "absent". dispatchResolvedRecord destructure unchanged; passes the text values straight through. apiVerifySimplexName switches from Just/Nothing pattern to a T.null guard with the same UX. Test fixtures updated. --- cabal.project | 2 +- src/Simplex/Chat/Library/Commands.hs | 17 +++++------ tests/ResolveNameTests.hs | 43 ++++++++++++++-------------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/cabal.project b/cabal.project index ed8a2fea4b..e7b30d6735 100644 --- a/cabal.project +++ b/cabal.project @@ -21,7 +21,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: c9c2d19074a809ba505f393b41aa20ac7b437aa7 + tag: 92b3d0492c5cf7730642774f925b6c1d61f04f54 source-repository-package type: git diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index 7dfa57e7ea..2e48d7615c 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -4730,10 +4730,12 @@ dispatchResolvedRecord vr nm user ni@SimplexNameInfo {nameType} NameRecord {nrSi -- | Pick the link from the @NameRecord@ matching the queried name type. -- A missing per-type field (record exists but advertises no link of this kind) --- is treated as "not found" — same UX as a local-store miss. -firstNameLink :: SimplexNameType -> Maybe Text -> Maybe Text -> SimplexNameInfo -> Either ChatError Text -firstNameLink nameType simplexChannel simplexContact ni = - maybe (Left $ ChatError $ CESimplexNameNotFound ni) Right link +-- is treated as "not found" — same UX as a local-store miss. The text fields +-- on 'NameRecord' use the empty string as the absent sentinel. +firstNameLink :: SimplexNameType -> Text -> Text -> SimplexNameInfo -> Either ChatError Text +firstNameLink nameType simplexChannel simplexContact ni + | T.null link = Left $ ChatError $ CESimplexNameNotFound ni + | otherwise = Right link where link = case nameType of NTPublicGroup -> simplexChannel @@ -4786,13 +4788,12 @@ apiVerifySimplexName user chatRef = do let resolvedLink = case nameType' of NTContact -> nrSimplexContact NTPublicGroup -> nrSimplexChannel - case resolvedLink of - Just lnk | linksMatch lnk storedLink -> do + if not (T.null resolvedLink) && linksMatch resolvedLink storedLink + then do ts <- liftIO getCurrentTime withStore' $ \db -> persistVerified db ts toView $ CEvtSimplexNameVerified user chatRef claim ts - _ -> - toView $ CEvtSimplexNameVerifyFailed user chatRef claim SNVFLinkMismatch + else toView $ CEvtSimplexNameVerifyFailed user chatRef claim SNVFLinkMismatch Left NameNotRegistered -> toView $ CEvtSimplexNameVerifyFailed user chatRef claim SNVFNameNotRegistered Left ResolverUnavailable -> diff --git a/tests/ResolveNameTests.hs b/tests/ResolveNameTests.hs index cd0bcf2be1..aeb76554cf 100644 --- a/tests/ResolveNameTests.hs +++ b/tests/ResolveNameTests.hs @@ -85,31 +85,32 @@ resolveNameTests = do other -> expectationFailure $ "expected ChatErrorAgent, got " <> show other -- firstNameLink is the pure link-picker used by dispatchResolvedRecord: -- it selects nrSimplexContact for NTContact, nrSimplexChannel for NTPublicGroup. - -- A Nothing for the queried type collapses to CESimplexNameNotFound so the UX - -- is identical to a local-store miss. + -- The text fields use the empty string as the "absent" sentinel; an empty + -- link for the queried type collapses to CESimplexNameNotFound so the UX is + -- identical to a local-store miss. describe "firstNameLink" $ do - it "picks nrSimplexContact for NTContact" $ - case firstNameLink NTContact (Just channelLink) (Just contactLink) aliceNi of + it "NTContact path picks simplexContact" $ + case firstNameLink NTContact channelLink contactLink aliceNi of Right lnk -> lnk `shouldBe` contactLink Left e -> expectationFailure $ "expected Right, got " <> show e - it "picks nrSimplexChannel for NTPublicGroup" $ - case firstNameLink NTPublicGroup (Just channelLink) (Just contactLink) groupNi of + it "NTPublicGroup path picks simplexChannel" $ + case firstNameLink NTPublicGroup channelLink contactLink groupNi of Right lnk -> lnk `shouldBe` channelLink Left e -> expectationFailure $ "expected Right, got " <> show e - it "returns CESimplexNameNotFound when nrSimplexContact is Nothing for NTContact" $ - case firstNameLink NTContact (Just channelLink) Nothing aliceNi of + it "empty Text returns NotFound" $ + case firstNameLink NTContact "" "" aliceNi of Left (ChatError (CESimplexNameNotFound ni)) -> ni `shouldBe` aliceNi other -> expectationFailure $ "expected CESimplexNameNotFound, got " <> show other - it "returns CESimplexNameNotFound when nrSimplexChannel is Nothing for NTPublicGroup" $ - case firstNameLink NTPublicGroup Nothing (Just contactLink) groupNi of + -- Each name advertises a per-type link; cross-type fallback would silently + -- connect to the wrong target, so a populated off-type slot must not satisfy + -- the queried type. + it "cross-type contact link with NTPublicGroup returns NotFound" $ + case firstNameLink NTPublicGroup "" contactLink groupNi of Left (ChatError (CESimplexNameNotFound ni)) -> ni `shouldBe` groupNi other -> expectationFailure $ "expected CESimplexNameNotFound, got " <> show other - -- NTContact ignores nrSimplexChannel even when nrSimplexContact is Nothing. - -- The resolver-side semantics say each name advertises a per-type link; - -- cross-type fallback would silently connect to the wrong target. - it "does not fall back to nrSimplexChannel for NTContact" $ - case firstNameLink NTContact (Just channelLink) Nothing aliceNi of - Left (ChatError (CESimplexNameNotFound _)) -> pure () + it "cross-type channel link with NTContact returns NotFound" $ + case firstNameLink NTContact channelLink "" aliceNi of + Left (ChatError (CESimplexNameNotFound ni)) -> ni `shouldBe` aliceNi other -> expectationFailure $ "expected CESimplexNameNotFound, got " <> show other -- linksMatch is the byte-equal-after-normalize comparator that gates -- APIVerifySimplexName. The agent's simplex:/ scheme and the server-hostname @@ -192,11 +193,11 @@ sampleRecord :: NameRecord sampleRecord = NameRecord { nrName = "alice", - nrNickname = Nothing, - nrWebsite = Nothing, - nrLocation = Nothing, - nrSimplexContact = Nothing, - nrSimplexChannel = Nothing, + nrNickname = "", + nrWebsite = "", + nrLocation = "", + nrSimplexContact = "", + nrSimplexChannel = "", nrEth = Nothing, nrBtc = Nothing, nrXmr = Nothing,