diff --git a/bots/api/COMMANDS.md b/bots/api/COMMANDS.md index 67cea33777..506efc1661 100644 --- a/bots/api/COMMANDS.md +++ b/bots/api/COMMANDS.md @@ -58,6 +58,7 @@ This file is generated automatically. - [APISetGroupCustomData](#apisetgroupcustomdata) - [APISetContactCustomData](#apisetcontactcustomdata) - [APISetUserAutoAcceptMemberContacts](#apisetuserautoacceptmembercontacts) +- [APIVerifySimplexName](#apiverifysimplexname) [User profile commands](#user-profile-commands) - [ShowActiveUser](#showactiveuser) @@ -1859,6 +1860,42 @@ ChatCmdError: Command error (only used in WebSockets API). --- +### APIVerifySimplexName + +Verify a contact's or group's claimed SimpleX name by RSLV-resolving the claim and comparing the resolved link to the peer's stored connection link. Synchronously returns `CRCmdOk`; the verification outcome is delivered asynchronously via [CEvtSimplexNameVerified](./EVENTS.md#cevtsimplexnameverified) or [CEvtSimplexNameVerifyFailed](./EVENTS.md#cevtsimplexnameverifyfailed). + +*Network usage*: interactive. + +**Parameters**: +- chatRef: [ChatRef](./TYPES.md#chatref) + +**Syntax**: + +``` +/_verify simplex name +``` + +```javascript +'/_verify simplex name ' + ChatRef.cmdString(chatRef) // JavaScript +``` + +```python +'/_verify simplex name ' + ChatRef_cmd_string(chatRef) # Python +``` + +**Responses**: + +CmdOk: Ok. +- type: "cmdOk" +- user_: [User](./TYPES.md#user)? + +ChatCmdError: Command error (only used in WebSockets API). +- type: "chatCmdError" +- chatError: [ChatError](./TYPES.md#chaterror) + +--- + + ## User profile commands Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents). diff --git a/bots/api/EVENTS.md b/bots/api/EVENTS.md index 2ac3af0133..32d2d9aeda 100644 --- a/bots/api/EVENTS.md +++ b/bots/api/EVENTS.md @@ -11,6 +11,9 @@ This file is generated automatically. - [ReceivedContactRequest](#receivedcontactrequest) - [NewMemberContactReceivedInv](#newmembercontactreceivedinv) - [SimplexNameConflict](#simplexnameconflict) + - [SimplexNameVerified](#simplexnameverified) + - [SimplexNameVerifyFailed](#simplexnameverifyfailed) + - [SimplexNameUnverified](#simplexnameunverified) - [ContactSndReady](#contactsndready) [Message events](#message-events) @@ -176,6 +179,47 @@ A peer's profile update claimed a SimpleX name (`#name.simplex` / `@name.simplex --- +### SimplexNameVerified + +RSLV verification of a contact's or group's SimpleX name claim succeeded: the resolved link matches the peer's stored connection link and `simplex_name_verified_at` has been written. Emitted asynchronously after [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname). + +**Record type**: +- type: "simplexNameVerified" +- user: [User](./TYPES.md#user) +- chatRef: [ChatRef](./TYPES.md#chatref) +- simplexName: [SimplexNameInfo](./TYPES.md#simplexnameinfo) +- verifiedAt: UTCTime + +--- + + +### SimplexNameVerifyFailed + +RSLV verification of a SimpleX name claim did not succeed. `reason` indicates the cause: `SNVFLinkMismatch` (resolved link does not match stored link), `SNVFNameNotRegistered` (no on-chain record exists), or `SNVFResolverError` (transport / proxy failure, with the agent error inline). The `simplex_name` claim is **not** cleared. Emitted asynchronously after [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname). + +**Record type**: +- type: "simplexNameVerifyFailed" +- user: [User](./TYPES.md#user) +- chatRef: [ChatRef](./TYPES.md#chatref) +- simplexName: [SimplexNameInfo](./TYPES.md#simplexnameinfo) +- reason: [SimplexNameVerifyFailReason](./TYPES.md#simplexnameverifyfailreason) + +--- + + +### SimplexNameUnverified + +A peer's incoming profile update (XInfo / XGrpInfo) carries a SimpleX name claim that the user has not yet verified — i.e. `simplex_name_verified_at` is NULL. Bots / UI may surface an unverified indicator next to the contact / group name; the user can clear it by invoking [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname). + +**Record type**: +- type: "simplexNameUnverified" +- user: [User](./TYPES.md#user) +- chatRef: [ChatRef](./TYPES.md#chatref) +- simplexName: [SimplexNameInfo](./TYPES.md#simplexnameinfo) + +--- + + ### ContactSndReady Connecting via 1-time invitation or after accepting contact request. diff --git a/bots/api/TYPES.md b/bots/api/TYPES.md index 70c90d108e..2451048137 100644 --- a/bots/api/TYPES.md +++ b/bots/api/TYPES.md @@ -172,6 +172,7 @@ This file is generated automatically. - [SimplexNameDomain](#simplexnamedomain) - [SimplexNameInfo](#simplexnameinfo) - [SimplexNameType](#simplexnametype) +- [SimplexNameVerifyFailReason](#simplexnameverifyfailreason) - [SimplexTLD](#simplextld) - [SndCIStatusProgress](#sndcistatusprogress) - [SndConnEvent](#sndconnevent) @@ -1756,6 +1757,7 @@ Error: - chatDeleted: bool - customData: JSONObject? - simplexName: [SimplexNameInfo](#simplexnameinfo)? +- simplexNameVerifiedAt: UTCTime? --- @@ -2304,6 +2306,7 @@ MemberSupport: - viaGroupLinkUri: string? - groupKeys: [GroupKeys](#groupkeys)? - simplexName: [SimplexNameInfo](#simplexnameinfo)? +- simplexNameVerifiedAt: UTCTime? --- @@ -3543,6 +3546,23 @@ A_QUEUE: - "contact" +--- + +## SimplexNameVerifyFailReason + +**Discriminated union type**: + +LinkMismatch: +- type: "linkMismatch" + +NameNotRegistered: +- type: "nameNotRegistered" + +ResolverError: +- type: "resolverError" +- agentError: [AgentErrorType](#agenterrortype) + + --- ## SimplexTLD diff --git a/bots/src/API/Docs/Commands.hs b/bots/src/API/Docs/Commands.hs index 8b45d09a4e..42092bd7c3 100644 --- a/bots/src/API/Docs/Commands.hs +++ b/bots/src/API/Docs/Commands.hs @@ -151,7 +151,10 @@ chatCommandsDocsData = ("APIDeleteChat", [], "Delete chat.", ["CRContactDeleted", "CRContactConnectionDeleted", "CRGroupDeletedUser", "CRChatCmdError"], [], Just UNBackground, "/_delete " <> Param "chatRef" <> " " <> Param "chatDeleteMode"), ("APISetGroupCustomData", [], "Set group custom data.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set custom #" <> Param "groupId" <> Optional "" (" " <> Json "$0") "customData"), ("APISetContactCustomData", [], "Set contact custom data.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set custom @" <> Param "contactId" <> Optional "" (" " <> Json "$0") "customData"), - ("APISetUserAutoAcceptMemberContacts", [], "Set auto-accept member contacts.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set accept member contacts " <> Param "userId" <> " " <> OnOff "onOff") + ("APISetUserAutoAcceptMemberContacts", [], "Set auto-accept member contacts.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set accept member contacts " <> Param "userId" <> " " <> OnOff "onOff"), + -- Resolves the chat row's simplex_name claim via RSLV and compares the resolved per-type link to the peer's stored connection link. + -- On match emits [CEvtSimplexNameVerified](./EVENTS.md#cevtsimplexnameverified); on mismatch or resolver failure emits [CEvtSimplexNameVerifyFailed](./EVENTS.md#cevtsimplexnameverifyfailed). + ("APIVerifySimplexName", [], "Verify a contact's or group's claimed SimpleX name by RSLV-resolving the claim and comparing the resolved link to the peer's stored connection link. Synchronously returns `CRCmdOk`; the verification outcome is delivered asynchronously via [CEvtSimplexNameVerified](./EVENTS.md#cevtsimplexnameverified) or [CEvtSimplexNameVerifyFailed](./EVENTS.md#cevtsimplexnameverifyfailed).", ["CRCmdOk", "CRChatCmdError"], [], Just UNInteractive, "/_verify simplex name " <> Param "chatRef") -- ("APIChatItemsRead", [], "Mark items as read.", ["CRItemsReadForChat"], [], Nothing, ""), -- ("APIChatRead", [], "Mark chat as read.", ["CRCmdOk"], [], Nothing, ""), -- ("APIChatUnread", [], "Mark chat as unread.", ["CRCmdOk"], [], Nothing, ""), diff --git a/bots/src/API/Docs/Events.hs b/bots/src/API/Docs/Events.hs index db2b2fc777..6a41e9ba66 100644 --- a/bots/src/API/Docs/Events.hs +++ b/bots/src/API/Docs/Events.hs @@ -68,6 +68,9 @@ chatEventsDocsData = ("CEvtReceivedContactRequest", "Contact request received.\n\nThis event is only sent when auto-accept is disabled.\n\nThe request needs to be accepted using [APIAcceptContact](./COMMANDS.md#apiacceptcontact) command"), ("CEvtNewMemberContactReceivedInv", "Received invitation to connect directly with a group member.\n\nThis event only needs to be processed to associate contact with group, the connection will proceed automatically."), ("CEvtSimplexNameConflict", "A peer's profile update claimed a SimpleX name (`#name.simplex` / `@name.simplex`) that was already held locally by another contact or group. The displaced row's `simplex_name` is set to NULL and the claim moves to the newer row; this event surfaces the displacement so the bot can warn the user about a possible impersonation."), + ("CEvtSimplexNameVerified", "RSLV verification of a contact's or group's SimpleX name claim succeeded: the resolved link matches the peer's stored connection link and `simplex_name_verified_at` has been written. Emitted asynchronously after [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname)."), + ("CEvtSimplexNameVerifyFailed", "RSLV verification of a SimpleX name claim did not succeed. `reason` indicates the cause: `SNVFLinkMismatch` (resolved link does not match stored link), `SNVFNameNotRegistered` (no on-chain record exists), or `SNVFResolverError` (transport / proxy failure, with the agent error inline). The `simplex_name` claim is **not** cleared. Emitted asynchronously after [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname)."), + ("CEvtSimplexNameUnverified", "A peer's incoming profile update (XInfo / XGrpInfo) carries a SimpleX name claim that the user has not yet verified — i.e. `simplex_name_verified_at` is NULL. Bots / UI may surface an unverified indicator next to the contact / group name; the user can clear it by invoking [APIVerifySimplexName](./COMMANDS.md#apiverifysimplexname)."), ("CEvtContactSndReady", "Connecting via 1-time invitation or after accepting contact request.\n\nAfter this event bot can send messages to this contact.") -- JOINED ] ), diff --git a/bots/src/API/Docs/Types.hs b/bots/src/API/Docs/Types.hs index 3a5633736a..6934321241 100644 --- a/bots/src/API/Docs/Types.hs +++ b/bots/src/API/Docs/Types.hs @@ -352,6 +352,7 @@ chatTypesDocsData = (sti @SimplexNameDomain, STRecord, "", [], "", ""), (sti @SimplexNameInfo, STRecord, "", [], "", ""), (sti @SimplexNameType, STEnum, "NT", [], "", ""), + (sti @SimplexNameVerifyFailReason, STUnion, "SNVF", [], "", ""), (sti @SimplexTLD, STEnum, "TLD", [], "", ""), (sti @SMPAgentError, STUnion, "", [], "", ""), (sti @SndCIStatusProgress, STEnum, "SSP", [], "", ""), @@ -573,6 +574,7 @@ deriving instance Generic SimplexNameConflictEntity deriving instance Generic SimplexNameDomain deriving instance Generic SimplexNameInfo deriving instance Generic SimplexNameType +deriving instance Generic SimplexNameVerifyFailReason deriving instance Generic SimplexTLD deriving instance Generic SMPAgentError deriving instance Generic SndCIStatusProgress diff --git a/packages/simplex-chat-client/types/typescript/src/commands.ts b/packages/simplex-chat-client/types/typescript/src/commands.ts index 46a3d8b27b..e25a2d8fc4 100644 --- a/packages/simplex-chat-client/types/typescript/src/commands.ts +++ b/packages/simplex-chat-client/types/typescript/src/commands.ts @@ -681,6 +681,20 @@ export namespace APISetUserAutoAcceptMemberContacts { } } +// Verify a contact's or group's claimed SimpleX name by RSLV-resolving the claim and comparing the resolved link to the peer's stored connection link. Synchronously returns `CRCmdOk`; the verification outcome is delivered asynchronously via [CEvtSimplexNameVerified](./EVENTS.md#cevtsimplexnameverified) or [CEvtSimplexNameVerifyFailed](./EVENTS.md#cevtsimplexnameverifyfailed). +// Network usage: interactive. +export interface APIVerifySimplexName { + chatRef: T.ChatRef +} + +export namespace APIVerifySimplexName { + export type Response = CR.CmdOk | CR.ChatCmdError + + export function cmdString(self: APIVerifySimplexName): string { + return '/_verify simplex name ' + T.ChatRef.cmdString(self.chatRef) + } +} + // User profile commands // Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents). diff --git a/packages/simplex-chat-client/types/typescript/src/events.ts b/packages/simplex-chat-client/types/typescript/src/events.ts index 020b8077e4..a3299acdf4 100644 --- a/packages/simplex-chat-client/types/typescript/src/events.ts +++ b/packages/simplex-chat-client/types/typescript/src/events.ts @@ -10,6 +10,9 @@ export type ChatEvent = | CEvt.ReceivedContactRequest | CEvt.NewMemberContactReceivedInv | CEvt.SimplexNameConflict + | CEvt.SimplexNameVerified + | CEvt.SimplexNameVerifyFailed + | CEvt.SimplexNameUnverified | CEvt.ContactSndReady | CEvt.NewChatItems | CEvt.ChatItemReaction @@ -64,6 +67,9 @@ export namespace CEvt { | "receivedContactRequest" | "newMemberContactReceivedInv" | "simplexNameConflict" + | "simplexNameVerified" + | "simplexNameVerifyFailed" + | "simplexNameUnverified" | "contactSndReady" | "newChatItems" | "chatItemReaction" @@ -158,6 +164,29 @@ export namespace CEvt { displacedFrom: string } + export interface SimplexNameVerified extends Interface { + type: "simplexNameVerified" + user: T.User + chatRef: T.ChatRef + simplexName: T.SimplexNameInfo + verifiedAt: string // ISO-8601 timestamp + } + + export interface SimplexNameVerifyFailed extends Interface { + type: "simplexNameVerifyFailed" + user: T.User + chatRef: T.ChatRef + simplexName: T.SimplexNameInfo + reason: T.SimplexNameVerifyFailReason + } + + export interface SimplexNameUnverified extends Interface { + type: "simplexNameUnverified" + user: T.User + chatRef: T.ChatRef + simplexName: T.SimplexNameInfo + } + export interface ContactSndReady extends Interface { type: "contactSndReady" user: T.User diff --git a/packages/simplex-chat-client/types/typescript/src/types.ts b/packages/simplex-chat-client/types/typescript/src/types.ts index 0cb27981c6..e8b9fdf3c8 100644 --- a/packages/simplex-chat-client/types/typescript/src/types.ts +++ b/packages/simplex-chat-client/types/typescript/src/types.ts @@ -2025,6 +2025,7 @@ export interface Contact { chatDeleted: boolean customData?: object simplexName?: SimplexNameInfo + simplexNameVerifiedAt?: string // ISO-8601 timestamp } export type ContactAddressPlan = @@ -2619,6 +2620,7 @@ export interface GroupInfo { viaGroupLinkUri?: string groupKeys?: GroupKeys simplexName?: SimplexNameInfo + simplexNameVerifiedAt?: string // ISO-8601 timestamp } export interface GroupKeys { @@ -3932,6 +3934,32 @@ export enum SimplexNameType { Contact = "contact", } +export type SimplexNameVerifyFailReason = + | SimplexNameVerifyFailReason.LinkMismatch + | SimplexNameVerifyFailReason.NameNotRegistered + | SimplexNameVerifyFailReason.ResolverError + +export namespace SimplexNameVerifyFailReason { + export type Tag = "linkMismatch" | "nameNotRegistered" | "resolverError" + + interface Interface { + type: Tag + } + + export interface LinkMismatch extends Interface { + type: "linkMismatch" + } + + export interface NameNotRegistered extends Interface { + type: "nameNotRegistered" + } + + export interface ResolverError extends Interface { + type: "resolverError" + agentError: AgentErrorType + } +} + export enum SimplexTLD { Simplex = "simplex", Testing = "testing", diff --git a/packages/simplex-chat-python/src/simplex_chat/types/_commands.py b/packages/simplex-chat-python/src/simplex_chat/types/_commands.py index d1ee8ec2d3..a64752ad44 100644 --- a/packages/simplex-chat-python/src/simplex_chat/types/_commands.py +++ b/packages/simplex-chat-python/src/simplex_chat/types/_commands.py @@ -596,6 +596,18 @@ def APISetUserAutoAcceptMemberContacts_cmd_string(self: APISetUserAutoAcceptMemb APISetUserAutoAcceptMemberContacts_Response = CR.CmdOk | CR.ChatCmdError +# Verify a contact's or group's claimed SimpleX name by RSLV-resolving the claim and comparing the resolved link to the peer's stored connection link. Synchronously returns `CRCmdOk`; the verification outcome is delivered asynchronously via [CEvtSimplexNameVerified](./EVENTS.md#cevtsimplexnameverified) or [CEvtSimplexNameVerifyFailed](./EVENTS.md#cevtsimplexnameverifyfailed). +# Network usage: interactive. +class APIVerifySimplexName(TypedDict): + chatRef: "T.ChatRef" + + +def APIVerifySimplexName_cmd_string(self: APIVerifySimplexName) -> str: + return '/_verify simplex name ' + T.ChatRef_cmd_string(self['chatRef']) + +APIVerifySimplexName_Response = CR.CmdOk | CR.ChatCmdError + + # User profile commands # Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents). diff --git a/packages/simplex-chat-python/src/simplex_chat/types/_events.py b/packages/simplex-chat-python/src/simplex_chat/types/_events.py index 9698323ce9..581df22a60 100644 --- a/packages/simplex-chat-python/src/simplex_chat/types/_events.py +++ b/packages/simplex-chat-python/src/simplex_chat/types/_events.py @@ -43,6 +43,26 @@ class SimplexNameConflict(TypedDict): claimedBy: str displacedFrom: str +class SimplexNameVerified(TypedDict): + type: Literal["simplexNameVerified"] + user: "T.User" + chatRef: "T.ChatRef" + simplexName: "T.SimplexNameInfo" + verifiedAt: str # ISO-8601 timestamp + +class SimplexNameVerifyFailed(TypedDict): + type: Literal["simplexNameVerifyFailed"] + user: "T.User" + chatRef: "T.ChatRef" + simplexName: "T.SimplexNameInfo" + reason: "T.SimplexNameVerifyFailReason" + +class SimplexNameUnverified(TypedDict): + type: Literal["simplexNameUnverified"] + user: "T.User" + chatRef: "T.ChatRef" + simplexName: "T.SimplexNameInfo" + class ContactSndReady(TypedDict): type: Literal["contactSndReady"] user: "T.User" @@ -339,6 +359,9 @@ ChatEvent = ( | ReceivedContactRequest | NewMemberContactReceivedInv | SimplexNameConflict + | SimplexNameVerified + | SimplexNameVerifyFailed + | SimplexNameUnverified | ContactSndReady | NewChatItems | ChatItemReaction @@ -386,7 +409,7 @@ ChatEvent = ( | ChatErrors ) -ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "simplexNameConflict", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "sentGroupInvitation", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "messageError", "chatError", "chatErrors"] +ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "simplexNameConflict", "simplexNameVerified", "simplexNameVerifyFailed", "simplexNameUnverified", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "sentGroupInvitation", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "messageError", "chatError", "chatErrors"] class OnEventDecorator(Protocol): @@ -433,6 +456,24 @@ class OnEventDecorator(Protocol): Callable[["SimplexNameConflict"], Awaitable[None]], ]: ... + @overload + def __call__(self, event: Literal["simplexNameVerified"], /) -> Callable[ + [Callable[["SimplexNameVerified"], Awaitable[None]]], + Callable[["SimplexNameVerified"], Awaitable[None]], + ]: ... + + @overload + def __call__(self, event: Literal["simplexNameVerifyFailed"], /) -> Callable[ + [Callable[["SimplexNameVerifyFailed"], Awaitable[None]]], + Callable[["SimplexNameVerifyFailed"], Awaitable[None]], + ]: ... + + @overload + def __call__(self, event: Literal["simplexNameUnverified"], /) -> Callable[ + [Callable[["SimplexNameUnverified"], Awaitable[None]]], + Callable[["SimplexNameUnverified"], Awaitable[None]], + ]: ... + @overload def __call__(self, event: Literal["contactSndReady"], /) -> Callable[ [Callable[["ContactSndReady"], Awaitable[None]]], diff --git a/packages/simplex-chat-python/src/simplex_chat/types/_types.py b/packages/simplex-chat-python/src/simplex_chat/types/_types.py index a049236340..45110a3007 100644 --- a/packages/simplex-chat-python/src/simplex_chat/types/_types.py +++ b/packages/simplex-chat-python/src/simplex_chat/types/_types.py @@ -1429,6 +1429,7 @@ class Contact(TypedDict): chatDeleted: bool customData: NotRequired[dict[str, object]] simplexName: NotRequired["SimplexNameInfo"] + simplexNameVerifiedAt: NotRequired[str] # ISO-8601 timestamp class ContactAddressPlan_ok(TypedDict): type: Literal["ok"] @@ -1841,6 +1842,7 @@ class GroupInfo(TypedDict): viaGroupLinkUri: NotRequired[str] groupKeys: NotRequired["GroupKeys"] simplexName: NotRequired["SimplexNameInfo"] + simplexNameVerifiedAt: NotRequired[str] # ISO-8601 timestamp class GroupKeys(TypedDict): publicGroupId: str @@ -2748,6 +2750,24 @@ class SimplexNameInfo(TypedDict): SimplexNameType = Literal["publicGroup", "contact"] +class SimplexNameVerifyFailReason_linkMismatch(TypedDict): + type: Literal["linkMismatch"] + +class SimplexNameVerifyFailReason_nameNotRegistered(TypedDict): + type: Literal["nameNotRegistered"] + +class SimplexNameVerifyFailReason_resolverError(TypedDict): + type: Literal["resolverError"] + agentError: "AgentErrorType" + +SimplexNameVerifyFailReason = ( + SimplexNameVerifyFailReason_linkMismatch + | SimplexNameVerifyFailReason_nameNotRegistered + | SimplexNameVerifyFailReason_resolverError +) + +SimplexNameVerifyFailReason_Tag = Literal["linkMismatch", "nameNotRegistered", "resolverError"] + SimplexTLD = Literal["simplex", "testing", "web"] SndCIStatusProgress = Literal["partial", "complete"]