mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 19:27:55 +00:00
755f6b409cf9e6ede9c33d500815af103ea6010f
87
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4aaeadd591 | store: rename badge service to StoreService | ||
|
|
1b329f41fb |
core: wallet for names (#7684)
* core: wallet key for name ownership (CLI only) A name has to be owned by an address the client can still derive after a restart or on a new device. This adds that key and nothing else. /wallet create makes one BIP-39 key per device and one BIP-44 account per chat profile under it, /wallet shows the address that would own the next name that profile buys, /wallet import and /wallet export move the key with its recovery phrase. A name key sits at m/44'/60'/<profile>'/0/<name>, which is ordinary BIP-44, so the phrase reaches the same addresses in other wallets. No signing, so nothing can be bought or edited yet. Split out of #7390 / #7425. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: pin simplexmq with eth crypto merged into master ab/eth-crypto forked before Crypto.Entitlement, which Chat.Badges imports, so the branch had to be merged with simplexmq master before it could be pinned here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: wallet review fixes, and show the derived addresses Concurrency: the account index is incremented in SQL and read back in the same transaction, so two profiles cannot be handed the same key. Importing a phrase is one transaction and single_seed is UNIQUE, so a phrase cannot be discarded in favour of a key created meanwhile, and a device cannot end up with two keys. Wallet commands are no longer forwarded to a remote host: the recovery phrase must not leave the device, and the raw command is logged there. /wallet delete removes the key, confirmed by the last word of the phrase, so creating a key before importing your own is no longer a dead end. /wallet now shows every profile on the key with the first two name addresses each, to check derivation against other wallets. Hidden profiles are left out, as they are by /users. A bad phrase no longer says which word was wrong. /wallet export uses the profile's own key. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: make the wallet an API, not a user-facing feature Names commands will use the wallet; users do not. The commands move to /_wallet, and the help section, its topic and the changelog entry are removed. The tests drive the API end to end. Comments cut to what the code does not say, dead exports removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: wallet export and delete act on the device key The key is one per device, so both commands read it directly instead of going through the active profile's account. A profile without an account of its own can now export, and the delete error says that the key goes for every profile on the device. The confirmation word is lowercased, as the phrase is when imported. Two known limitations are written down: account indexes restart at 0 after an import, so profiles are bound in the order they ask for a key, and the gap left by a hidden profile in the printed indexes shows that it exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: /_wallet delete takes no confirmation word The wallet is an API, and no other API command takes a typed confirmation: /_delete user takes the profile password. The word was also no barrier to a caller, which can read it from /_wallet export. Confirming belongs in the command that will wrap this one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: name the unique index on wallet_seeds The one key per device rule is meant to be lifted later. SQLite cannot drop a column with an inline UNIQUE, or its automatic index, so lifting it would have meant rebuilding the table. As a named index it is a DROP INDEX and a DROP COLUMN. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: export the secret of a single name key /_wallet export gives the seed mnemonic, /_wallet export <account> <name> gives the secret of one derived key, so a single name can be handed over without the seed. Both are what a wallet takes on import: the mnemonic as a recovery phrase, the secret as hex. The commands are named for what they return, APIWalletExportSeedMnemonic and APIWalletExportDerivedSecret, as the difference is which secret leaves the device. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: reject a key index BIP-32 cannot harden A.decimal wraps into Word32 and hardened leaves anything at or above 2^31 alone, so /_wallet export 4294967296 0 returned account 0's secret under the path m/44'/60'/0'/0/0. Handing out a different account's key for a mistyped index is the wrong failure for this command. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: /_wallet bind, and name the other profiles instead of numbering them Restoring a chat database older than the key loses which account each profile had, and the keys are still there, so /_wallet bind <account> sets it by hand. The counter moves past an account bound this way, and an account another profile holds is refused. /_wallet now shows the paths of the active profile only, and names the other profiles on the key. Their account indexes were the gap that showed a hidden profile exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: say same seed, not same key, for the other profiles Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: create makes the seed, bind claims a path The two were one command: on a device that already had a seed, /_wallet create only bound a profile. Now create makes the seed and refuses when one exists, and binds every profile that exists, as a new seed has no account that already owns a name. /_wallet import binds nothing. Which account a profile had is what an import is recovering, and the seed does not say, so the profile says it with /_wallet bind <account>. /_wallet bind with no account takes the next free one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: the known issue is now about bind, not import Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: create binds no profile either Create and import differed only in whether they bound a profile, which made the convenient one inconsistent. Neither binds now, so the store keeps one function for both, and a profile reaches an account only through bind. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: test the restore cases the key has to survive A database backed up after the key carries the key and the binding, so the restore is all of it and an import is refused. A database backed up before the key comes back with the profiles and no binding, so the phrase is imported and each profile says which account was its. A key imported before the database is restored is replaced by what the backup held. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: drop the types nothing reads, and say account where it means account AccountRef and WalletAccount were built and never read: deriveNameKey now returns the key, and the address comes from addressFromPrivateKey, which already exists. SeedId is a plain Int64 like every other row id here. The master key is derived once per command rather than once per name key, which is where PBKDF2 runs. A device has a key and a profile has an account, so /_wallet says "no account for this profile" rather than repeating "no wallet key", which is what it says when the device has none. Also: no "wallet: " in front of "bad chat command: ", strEncode for the address, the repeated seed lookup in one place, comments cut to what the code does not say, and the export test pins its addresses and secrets, including one whose first byte is zero. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: store the seed as bytes, and bind one account per profile On Postgres a bare ByteString binds as a text literal, so entropy with a backslash or a high bit was rejected and entropy with a zero byte was truncated: the BIP-39 test vector stored as an empty seed. Blob columns go through DB.Binary here, as every other one does. /_wallet bind with no account moved a profile that already had one to a fresh account, abandoning the old one without saying so. It refuses now; moving is asked for by number. The counter could walk past 2^31, where BIP-32 hardening folds every index back onto a low one, so a profile handed 2147483648 derived account 0's keys and printed account 0's path. Binding refuses once the counter is there, and a very long index is now rejected on its digit count rather than after reading it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: rfc for the keys that own names Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: pin simplexmq for the BIP-44 path, and use it ethereumPath now takes the address index, so the path a name key sits at is built once in the library rather than again here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: refuse an account index BIP-32 cannot harden, whichever way it arrives The counter path checked it, the explicit one did not, and the parser is not the only caller: processChatCommand takes APIWalletBind from library callers too. hardened leaves an index at or above 2^31 alone, so account i and i + 2^31 are the same key while the duplicate check compares the stored integers, and two profiles could hold one account's names. The rfc now says what hiding a profile from /_wallet does and does not protect: the seed is one per device, so whoever unlocks any profile can derive every account. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: pin simplexmq with the wordlist embedded from the upstream file Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: cut the rfc to what stands on its own Drops the references to other documents and to what is or is not in a pull request, so the design reads without them, and the list of tests, which restated their names and would drift. 164 lines to 134, against a median of 117 for the rfcs here that define schema. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: what the stealth meta address is for Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: the wallet is not only for names The seed, the accounts and the derivation are a wallet. Owning a name is the first thing it is used for, not what it is, and the title and the problem it solves now say so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: the reason for a key per name is that owners are public One address owning several names links them: whoever knows one name can read its owner and find the others. That is the reason, not the narrower export. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: give the reason for the counter before what it costs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: names are the device's, so drop the per-profile account A name's profile is the record it resolves to, not the key that owns it, so the account level was carrying a mapping nothing needs. It was also the only source of the profile to account ambiguity after a restore, of /_wallet bind, and of the index gap and the refusal that told a visible profile an account was held by one it cannot see. All of it goes. Names sit in account 0 from index 1. Index 0 is left unused so neither the names nor the profile accounts, which start at 1, claim the origin of both dimensions. users gains no columns at all now, so the migration is one CREATE TABLE. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: rfc for names counted per device Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: one command for the seed, whichever way it arrives create and import differed only in where the entropy came from and already shared one store function, so they are one command with the source named: /_wallet create new, or /_wallet create seed=<phrase>. Naming it means no seed is generated by typing a prefix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: the argument is a mnemonic, so name it one Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: the column holds entropy, so name it entropy The mnemonic comes back from the entropy exactly, which is what export returns, and the seed PBKDF2 derives from the mnemonic is computed when a key is needed and never stored. The column was the one thing called seed that is not the seed, which is why it needed a comment saying so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: 24 words is a choice, not a default Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: deleting the seed reports ok, not the empty wallet Delete re-ran /_wallet, so a successful delete printed "no wallet key", which is the same words the error uses and reads as a failure. There is nothing to show after a delete. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * docs: the export argument is an index, not a name Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * core: export says which kind of secret, so other kinds can follow /_wallet export name <k> rather than an index straight after export. The bare form stays the seed mnemonic, and a profile's key can be added beside the name one without the argument having to be guessed from its shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rvc3HbiWBTqbAvRT45G5oX * disencourage hidden profiles using names * let remote use wallet, but filter logs to avoid leaking secrets * change RFC wallet architecture to BIP-85 per profile and hardened paths for names * introduce keyring as the thing a profile binds to * restructure RFC * shorten * drop BIP85 and flattenhierarche. no keyrings * /goal iteration 4 - unconfirmed * /goal iteration 5 - unconfirmed * repin * rename to adapt * cut comments * next review round * minimize diff and align style even more * missing type mappings * fix review comments * self-review iteration 2 * self-review iteration 3 * self-review iteration 5 * iteration 6 * self-review iteration 9 * self-review iteration 10 * repin * rng preserve * refactor WalletSeed type, see mq wip * repin * infallibel wallet and account derivation * review iterations * repin to mq, derivation fallible again * repin * use deriveAddress, update simplexmq * simplexmq * add down migration for db and drop redundant masterkey field in db * repin to simplexmq PR * fable review fixes * iterations on /goal * treat hidden profiles same as normal ones. they can hold accounts now * reduce explicit types * repin mq * doc cosmetics * simplify * query plans * query plan * simplify * query plans * simplify more * fixes for comment ^^ --------- Co-authored-by: Alain Brenzikofer <alain@encointer.org> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
7306f3aeef |
core: alerts with information about registering names (#7653)
* minimal api change * embed status. reduce * drop fake owner change * no-valid-link fix * add UX flow for name lookups * diagram edits * corrections * update name lookup API * manual renaming * implement core + cli * implement UI * fix * build iOS app blindly * shrink diff * fix review comments * review iterations * opuse 5.5 /goal iterations * fixes EP review * fixes * fixes * short goal iterations * refactor core-UI API to NameWarning with logic in core * diff cosmetics * simplify and normalize diagram * add excalidraw normalizer script and test git hook * cosmetics * commit wireframe collab doc to repo as README * review round on UX coverage * iterate on /goal * iterate on /goal * add tests * iterate on /goal * fix freshness bug with local chats: When core marks a chat verified for a name, it now first un-verifies the user's other chats of the same kind: - a contact name covers contacts and business chats; - a channel name covers channels. * align app divergences * docs fixes * iterations on /goal * align excalidraw * align and simplify core/UI/UXcanvas * 27 rounds of /goal * review * core: simplify connect plan with name lookup * simplify * cache names in a separate table * cache names resolution * wip * all * fix * remove cache * update plans * simplify * bot types * change types * simplify * update bot types * remove review * update view, tests * simplify "unverify" * update query plan * changes * simplify * test helpers * simpler * update query plans * fix * query plans * query plans * fixes * query plans --------- Co-authored-by: Alain Brenzikofer <alain@encointer.org> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
07c363849b |
core, ui: invite member of one group to another group (#7682)
* rfc: invite member of one group to another group * update * update * implement * version * update * do not show error if contact was removed when joining group --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
2e56d32b52 |
core: badge presentations in profiles (#7573)
* badge presentation in groups * fix tests * badge presentations in profiles * update simplexmq * change types * badge profile presentations * improvements * remove proof from cards, send owner public key for channel to relay * add test * merge migrations * update * prevent fallback to PHTest * fixes * many fixes * fixes * fixes * cleanup * improve * query plans * fix test * diff --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
643a9afad6 |
bots: SimpleX Calculator demo bot (#7583)
* bots: SimpleX Calculator demo bot * refactor * use local server in test * simplify * icon * simplify * expression * replies * improve * log * update name in bot address * @simplex-chat/type: 0.12.0 * simplex-chat nodejs: 7.1.0-beta.4.2 * update dependencies * option to add domain to bot address --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
3af6e2abfe |
core: store extended contact and group preferences, for forward compatibility (#7506)
* core: store extended contact and group preferences, for forward compatibility * simiplify * fix * fix bot api types * query plans --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
c8f20bcc91 |
core, libs: configurable queue size, library fixes (#7542)
* core: add chat_migrate_init_queue FFI export * bots: fix BadgeServiceErrorCode API type * nodejs: pass required command fields * nodejs: fix migration error types * nodejs: install libsimplex from SIMPLEX_LIBS_DIR * nodejs: add queue size option * nodejs: regenerate docs * python: add queue size option * bots: pass incognito in APIConnect * nodejs: accept documented success responses * python: accept documented success responses * nodejs: dispatch each bot message once * nodejs: fix startChat events loop lifecycle * nodejs, python: parse multi-line bot commands * nodejs: fix file buffer handling in addon * nodejs: keep events loop when chat stop fails * python: fix send_and_wait race, load lib off loop * python: make queue size export optional * nodejs: receive events on a dedicated thread * nodejs: release haskell thread after receive * python: receive on a dedicated thread per chat * python: test receive shutdown order * nodejs: one receive thread per chat controller * nodejs: harden receiver shutdown and tests * nodejs: stop chat before closing store * python: stop chat before closing store * nodejs, python: harden close regression and retry * python: free results with ucrt on windows * nodejs: enable c++ exceptions on mac and windows |
||
|
|
c8466b2010 |
core: refactor groups (#7503)
* core: refactor groups * refactor * refactor * refactor * refactor * refactor * rename * refactor * remove * rename * diff * simplify * relay requests * bot types * check useRelays * refactor * query plans --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
c7b3e362ec | core, ui: badge credential details in developer tools (#7527) | ||
|
|
fea9f482cf | core: update bot api and query plans | ||
|
|
bac8d187ba | Merge branch 'master' into badges | ||
|
|
ca114a7a2a |
core: option to limit the max number of loaded chats (#7499)
* core: option to limit the max number of loaded chats * update bot api --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
5ffbe733a8 |
core: attach badge proofs to files over size limit (#7455)
* core: attach badge proofs to files over size limit * types * more types * implement file badge proofs * tests * move file limits to config, add tests * more tests, work correctly in "send as group" case * fix races in tests * group badge tests * query plans * add history support, fixes * simplify * refactor * refactor * type * restructure schema for proofs * rename, refactor * refactor * fix, refactor * refactor * ui * comments * alerts * update nix, ios library * updare sharing * update simplexmq * update text * improve messages * api types * postgres schema * fix * test * query plans --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
47d32b674a |
bots: add APIs (#7494)
* docs: fix bot API surface - Fix missing space in APIShareMyAddress syntax expression which resulted in parse errors - Document missing `Connect` responses: `CRConnectionPlan`, `CRSentInvitationToContact`, `CRStartedConnectionToContact`, and `CRStartedConnectionToGroup` (relay channel links). - Document missing `CRUserProfileNoChange` responsed returned when `APISetProfileAddress` doesn't change the profile. - Expose remote control APIs to bots * website: improve sign-up forms (#7484) * website: improve sign-up forms * name --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * rename field * generic --------- Co-authored-by: a1akris <alkrivitskiy@pm.me> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
44773d0412 |
core: support message signing in p2p groups (#7312)
* core: support message signing in p2p groups * improve * add member key * distribute keys and sign * refactor * better query * map * sign in relay groups too * clean up * list * fix test * update bot types * some refactor * remove unnecessary condition * simplify * refactor * simplify * move * clean up * diff * diff * limit attempts for key sending * optimize * fix test * split * fuse * null * only mark as "key sent" when forwarder supports binary encoding * fix bot apis * fix some tests * add key distribution steps, and fix some tests * fix test * increase timeout * fix tests * fix more tests * simplify * disable test output * mark keys sent with invitations * fix test * fix test, query plans * unify signing of connection info packets * revert change to createNewGroup * create key at group/member creation * rename, remove liftIO * clean up * fix type * remove ad hoc key sending * update bot api * diff * reduce diff * failing test * fix sending messages in groups with members before version 18 * remove test delays * update query plans * update test * add tests * fix tests --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
f9bab17643 | core: renew badges monthly and alert when support ends (#7448) | ||
|
|
3ddf17dce5 | core: redeem badge codes (#7438) | ||
|
|
ecb008b792 |
core, ui: auto-accept group invitations per user profile (#7377)
* core, ui: auto-accept group invitations per user profile Add a per-profile toggle for auto-accepting group invitations, and regroup it with the existing contact-requests setting under a single Auto-accept section in Privacy & Security, relabelled "Contact requests in groups". The join is fully async. processGroupInvitation already had an async accept path, used when the invitation matches a group link the user opened: prepareAgentJoin + createMemberConnectionAsync + joinAgentConnectionAsync, with the outcome reported later against the CFJoinConn command id. Auto-accept takes that same path instead of going through APIJoinGroup, so it works while the app is closed and never blocks message processing. An auto-accepted invitation still records a CIRcvGroupInvitation item in the chat with the inviting contact, so there is a record of who added the user to which group. Two details worth noting for review: hostContact is reported to clients only for group links. Clients respond to it by replacing the transient host connection view with the group and removing that chat - correct for a group link, where the contact is a placeholder, but wrong for a plain invitation, where it is a real contact. A resent invitation returns the existing group, because createGroupInvitation is idempotent on inv_queue_info. The join therefore only runs while the membership is still GSMemInvited, so a resend cannot open a second connection. * booldef * order * refactor * update translation key * query plans * ios: export translations --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> |
||
|
|
31faceef73 | docs: add bot library APIs (#7334) | ||
|
|
e1a349b90f |
core: support contact addresses with DR keys, service requests (#7310)
* core: use double ratchet keys in contact address (#7278) * core: use double ratchet keys in contact address * use PQ from the first message * query plans * update simplexmq * api to rotate keys, option to show full links in CLI * shorter description * ui: add error parameters * disable DR in addresses * core: parameter for create address command to configure ratchet keys * add pqRatchet param to address-related commands * query plan * fix parser * fix kotlin --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * core: contact request rejection and service requests (#7292) * update simplexmq * implement service requests and rejections * tests * migration * fix migration * add api event and response * bot api, postgres migration * nix shas * bot types, rename property * update bot type * sign service requests * update bots api * query plan * update plan * update simplexmq * fix test, update bot api * fix bot api * resolve name for service request * refactor --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * update simplexmq * update simplexmq * test delays --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
f1418f9e55 |
core: drop support of chat versions older than 08/2024 (#7319)
* core: drop support of chat versions older than 08/2024 * fix encoding tests * skip failing tests * rename * fix * query plans * remove unused legacy code * remove more unused * remove unused * remove unused names --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
c00f9620e1 | bots api | ||
|
|
6e2995cab6 |
cli: add name, image and relay server address flags (#6944)
* cli: add --relay-address-server option for chat relay New CLI flag --relay-address-server SERVER selects the SMP server used for the chat relay address link created at startup. Only valid together with --relay; errors out otherwise. Threads Maybe SMPServerWithAuth through APICreateMyAddress to the new agent createConnection parameter. * cli: add --user-display-name option Selects or creates the active user non-interactively: - no active user: create one with the given display name - active user with matching localDisplayName: continue - active user with different name: exit with error Mutually exclusive with --create-bot-display-name. * cli: add --user-image-file option Sets the active user's profile image from a .png/.jpg/.jpeg file at startup. Reads file, base64-encodes as data URL, and updates the user profile directly in the DB - no notification is sent to existing contacts. Skips the update if the stored image already matches. Requires --user-display-name. * cli: address PR review comments - rename APICreateMyAddress field srv_ to server_ - extract repeated `loop` and putStrLn from createActiveUser via prompt where-clause - fuse u_ inspection: validate active user display name in the same case that creates the user when missing * cli: enforce profile image size limit in --user-image-file Reject the file if the encoded data URL exceeds 12500 bytes - matches the cap mobile and desktop UIs pass to resizeImageToStrSize for profile images. Without this, oversized images would be silently set on the user profile. * core: validate profile image size in chat commands Enforced in CreateActiveUser, updateProfile_, newGroup, runUpdateGroupProfile via checkProfileImageSize; max 12500 bytes (matches mobile UIs). * fix: thread new ChatOpts/CoreChatOpts fields through bot/test constructors * bots/docs: filter hidden params before type introspection Hide APICreateMyAddress server_ field so the bot doc generator does not try to introspect SMPServerWithAuth (an unregistered type). * core: validate full encoded profile size Add checkProfileSize / checkGroupProfileSize that encode the full ChatMessage and check against maxEncodedInfoLength, so a long displayName/bio combined with a near-max image is also caught at command time instead of failing later at send time with CEException. Run alongside the existing checkProfileImageSize (image-only cap of 12500 bytes, matching mobile UIs) in CreateActiveUser, updateProfile_, newGroup, runUpdateGroupProfile. Update genProfileImg to fit the cap. * cli: add --headless option for chat relay Skips interactive prompts (relay address creation, display name) so the chat relay can run non-interactively as a service. Requires --relay; creating a new profile also requires --user-display-name. * test: cover profile image size limit and address server Adds tests for two new capabilities: - profile image size validation rejects oversized images - /_address with a server pins the address to the requested SMP server * core: update simplexmq (pass optional SMP server to prepareConnectionLink) * cli: add /set profile image file, fix image flag Add "/set profile image file <path>" command to set the profile image from a .png/.jpg/.jpeg file in a running session. Make --user-image-file create-only: for an existing user it now no-ops with a note instead of failing with "chat not started" (the update ran before the chat controller was started). * core: unify image loading and profile size checks - loadImageFile (CLI) and readProfileImageFile (command) now share one loadImageData; removes the duplicated mime/base64 encoding and its decodeUtf8/safeDecodeUtf8 divergence. A missing --user-image-file no longer crashes with an uncaught IOException, and empty files are rejected. - checkProfileSize/checkGroupProfileSize share checkInfoSize. - --relay-address-server/--headless requires-relay checks use errorWithoutStackTrace, matching the adjacent validation (no callstack dump). * bots/docs: document UpdateProfileImageFromFile as a CLI command |
||
|
|
51ad366e8b | core, ui: message signing (#7115) | ||
|
|
6150b35a2f |
core, ui: resolve untyped domains (#7198)
* core: resolve untyped domains * CPError * only add domain when it has link of correct type * resolve first * handle errors * remove CPError * update UI types * remove unused name Co-authored-by: Evgeny <evgeny@poberezkin.com> * refactor connection plan * kotlin: show domain and alternative chat, haskell tests for dual domains * view/tests * update kotlin * dual domains accounting for business chats * refactor, fix * fix kotlin * remove comment * search * add resolve mode * local resolution * refactor, bot types * search both contact and channel by name * fix * fix searching business chats by name * fix ui * ios * fix ios * fix icon --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
10a814694c |
core, ui: support SimpleX names (#7045)
* deps: bump simplexmq for ConnectTarget * chat: migration adds simplex_name to contacts, groups, connections Nullable TEXT column on all three tables, with partial indexes on contacts(user_id, simplex_name) and groups(user_id, simplex_name) for the upcoming connectPlanName lookup. connections.simplex_name is the transient carrier from APIConnect -> XInfo handler, where the value is copied to contacts.simplex_name at delayed create. No reads or writes yet - column threading lands in subsequent commits. * tests: provide namesConfig = Nothing in smpServerCfg Follow-up to the simplexmq pin bump ( |
||
|
|
0e09b38ea6 | core: public groups - roster of privileged members (#7017) | ||
|
|
adb3fb8cb2 |
core: render web previews for channels (#7029)
* plan: web previews for channels
* types for recipient side to support channel web previews and domain names
* fix
* migrations
* update schema and api types
* update schema
* rename migrations
* core: render channel preview data
* core: render channel preview data in relays
* website: use cpp to inject JS functions
* JSC files
* remove directory.js
* channel preview renderer
* Revert "cli: fix redraw slowness (#6735)"
This reverts commit
|
||
|
|
37f7ed3126 | Merge branch 'stable' | ||
|
|
ad23da63d0 |
core: supporter badges using anonymous BBS credentials (#7040)
* core: supporter badges using anonymous BBS credentials * badges in profiles * badge in profiles * process badges * update simplexmq * update simplexmq * change types * fix migration * migration * update simplexmq * fix bot API, schema * fix postgresql build * refactor * postgresql schema * correctly set badges in all cases * badges ffi * plan, bot types * FFI * FFI: export badge symbols * add extra field * refactor badge types to GADT * configurable badge key * add badge to profile, test * ui: badge images * generate badge key and sign badge * badge sign in CLI * fix commands, ui * rename badges * Binary * image size, migration * update badge images, add public key * send badges in more cases * update UI, tests * bot types, schema * postgres schema * tone down badges * revert formula * refactor badges * smaller badges * badge position * better badge position * simpler * position * move position * update simplexmq * show badge after name * badge layout * fix badge * debug badge height * shift badge * fix badge in member name * bigger badge * badge layout * differentiate badge colors * more avatars for the user's profiles * refactor * remove color filter * alerts * multiple keys, old expired * use new BBS api * update badge keys, bot api * presentation header * simplify * parser * update iOS images * update public keys * query plans * update simplexmq * refactor badge types * simplexmq * bot api types * update simplexmq - commoncrypto flag * update simplexmq * pass commoncrypto flag to simplexmq in nix iOS build * ios ui * update core library, fixes * badge layout * badge size * badge gap * remove extensions * simplify * share badge in more events, reverify badge if verification failed * larger files with badges * allow sending larger files * simpler * update simplexmq * better decoder for badge keys * update simplexmq --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: shum <github.shum@liber.li> |
||
|
|
60e75aa398 | Merge branch 'stable' | ||
|
|
9bb2bec3fa |
plan: web previews for channels (#7022)
* plan: web previews for channels * types for recipient side to support channel web previews and domain names * fix * migrations * update schema and api types * update schema * rename migrations * core: check member role --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
9f93e87f56 | Merge branch 'stable' | ||
|
|
68fc1b5d22 |
core, ui: split SimplexNameDomain out of SimplexNameInfo (#7024)
* core, ui: split SimplexNameDomain out of SimplexNameInfo * core: bump simplexmq to b3f28948 (SimplexNameDomain split) * core: bump simplexmq to 4e2c9fc3 (StrEncoding split) * core: bump simplexmq to ee2ff402 (#1788 squash merge) * update sha256map.nix |
||
|
|
507a4de61c | Merge branch 'stable' | ||
|
|
68abd805d4 |
rfc: namespace (#7001)
* rfc: namespace * update rfc * markdown for names * record type, app "upgrade" alerts * update api types * rfc: change namespace syntax - now it is the usual namespace * update bot types * move types to simplexmq * core: refactore markdown * update simplexmq * better names * new names * update nix content hashes * fix * change valid name function * update simplexq, update valid name conditions * fixes Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com> * update simplexmq * fix localization * simpler * refactor * refactor * fix --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: simplex-chat-agent[bot] <287173099+simplex-chat-agent[bot]@users.noreply.github.com> |
||
|
|
fe6b5186e1 |
core: update simplexmq (receiving services) (#6212)
* core: update simplexmq * update agent api * update simplexmq * core: add flag to User to use client services * update simplexmq * cli command to toggle service for a user * test, fix * query plans, core/bot api types * remove local package reference * increase server queue size in tests * show client service status in users list * update query plans * cli: fix redraw slowness (#6735) * cli: add pland to fix redraw slowness * updtae doc * cli: decouple key reading from processing via TQueue * schema and bot types --------- Co-authored-by: sh <37271604+shumvgolove@users.noreply.github.com> |
||
|
|
92e9640e4f | core, ui: relay reject rejoin (#6978) | ||
|
|
9584992c83 |
simplex-chat-python: split Client from Bot, add request/response API (#6976)
* simplex-chat-python: split Client from Bot, add request/response API
Client is now the base class for SimpleX participants that talk TO
services (monitors, probes, automated participants). Bot extends Client
with server features (address, auto-accept, welcome, commands).
New methods on Client (inherited by Bot):
connect_to(link) idempotent contact handshake
send_and_wait(id, text) send a message and await the reply
events() async iterator over chat events
@on_message(contact_id=N) filter by sender in decorators
BotProfile renamed to Profile (alias kept). New ContactAlreadyExistsError
subclass for cleaner error handling.
* simplex-chat-python: narrow event payload type per @on_event tag
@client.on_event("contactConnected") now types the handler's event
parameter as CEvt.ContactConnected instead of the unnarrowed
CEvt.ChatEvent union — mirroring how @on_message narrows by
content_type.
The 50 overloads are generated by the Haskell codegen into _events.py
(as a Protocol class), so new events stay in sync automatically.
Client.on_event is exposed as a property typed as that Protocol; the
runtime implementation is unchanged.
|
||
|
|
e63c403623 |
simplex-chat-python: add python library (#6954)
* docs: simplex-chat-python design and implementation plan * bots: Python wire types codegen * simplex-chat-python: package scaffold * simplex-chat-python: native libsimplex loader * simplex-chat-python: async FFI wrappers * simplex-chat-python: ChatApi with 49 api methods * simplex-chat-python: Bot class with decorators and dispatch * simplex-chat-python: install CLI, example bot, README * simplex-chat-python: audit fixes * bots: regenerate API docs and types Catches up the markdown, TypeScript and Python codegen outputs with two upstream schema changes: - APIConnectPlan.connectionLink became optional (from sh/python-lib audit fixes); cmdString and EBNF syntax now reflect optional parameter. - APIAddGroupRelays command and CRGroupRelaysAdded/CRGroupRelaysAddFailed responses added in #6917 (relay management). The TS and markdown outputs were regenerated when #6917 landed but the Python types module only got the new entries with this regeneration. * core: refresh SQLite query plans after relay_inactive_at migration The M20260507_relay_inactive_at migration (#6917 / #6952) shifted the query plans that 'Save query plans' verifies. Regenerated via the test that owns those snapshots; no behavioral change. * bots: keep APIConnectPlan connectionLink as required parameter The prior audit-fixes commit changed the syntax expression to `Optional ...` because the Haskell field is `connectionLink :: Maybe AConnectionLink`. That misrepresents the API contract: the `Maybe` is purely an internal signal for link-parsing failure (the handler returns `CEInvalidConnReq` on `Nothing`), not API-level optionality. Callers MUST always pass a connection link. Revert the syntax expression to `Param "connectionLink"` and add a comment so the intent is preserved next time someone audits. Regenerates COMMANDS.md, commands.ts and _commands.py to match. |
||
|
|
6f8a07e4ea | core, ui: relay management - add, remove relays, synchronization to relay list (#6917) | ||
|
|
fefdea8ed0 |
support bot, bots: paginate chat scan (#6935)
* bots: document APIGetChats command and CRApiChats response * bots: regenerate API docs and TypeScript types * simplex-chat-nodejs: add apiGetChats * support bot: avoid OOM on large databases apiListGroups / apiListContacts return every record in one response and overflow V8's string allocation on large DBs. Replace list-then-find-by-id patterns with apiGetChat(type, id, 0) lookups, and the one genuine scan (refreshAllCards) with paginated apiGetChats, count=1000. * support bot: update test assertions to match current message text * bots: simplify PaginationByTime, expose only PTLast * simplex-chat-nodejs: bump types and nodejs versions |
||
|
|
63c278818e |
core: support chats in channels, send as owner in support chats (#6870)
* core: test support chats in channels, CLI defaults to sending as member in support chat * ui: enable support chats in channels * use correct scope when sending from UI * more readable * remove test output * show member support chat in channels * preference for support chats * ios: types for support preference * mp: support preference types * show support preference in UI * fix ios * make support preference optional in JSON parser * update string * change strings, pass parameters to prefs * refactor kotlin * take support preference into account * refactor core * do not show broadcast placeholder in support scope * move role check, add pref check on update * support preference test (failing) * fix version * fix tests * warning alert when enabling chats with admins * revert on dismiss * update text and icons * query plans --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
53a225a0c9 |
directory: periodically update subscriber counts for registered channels and re-verify links and ownership (#6879)
* directory: update subscriber counts for registered channels and re-verify links and ownership * refactor * rename * mapM_ * refactor * refactor * refactor more * more * different approach * rename * test * bot api types --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
f3547878cc |
directory: support public channels and relay-based groups (#6840)
* directory: support public channels and relay-based groups (plan) * types * amend types * directory types, resolve known link * implementation, test fails * fix test * fix test * more test * minimal test * more test * debug test * clean up * remove debug logs * refactor * use group/channel terms correctly * remove unsupported commands * manage profile update * owner left the channel * more tests, correct response to sent link * re-registration * /help and /link commands * correct listing for channels * fix test * fix bot api * refactor * do not include link data in GLPKnown * refactor * diff * undo refactor * simplify * remove harness test * remove flip * add v6.5 app requirement for channels * add website support * update bot api types * correct member count, fix test * members -> subscribers * add link to channel description * fix css * move version note --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
2eb25d124f | core, ui: better error on failed channel creation (#6825) | ||
|
|
30ae0d864c |
core: share links to channels and verify shared links when connecting (#6810)
* core: share links to channels and verify shared links when connecting * refactor * improve * refactor case * simplify * exctract encodeChatBinding * share api * corrections Co-authored-by: Evgeny <evgeny@poberezkin.com> * tests * verify signature in the tests * drop signature if context does not match on reception * try to test "fake" forward * fix * fix direct chat sharing test * channel test * sign link * rename api * refactor view * chal link item CLI view, tests * clean up * share channel in channel as channel * query plan * fix test * refactor * whitespace * simpler * refactor * dont use partial field update --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
6f21826579 |
core, ui: chat item to show message error (#6785)
* core: chat item to show message error * ui: chat item for removed messages * remove local maven repo * command to test dropped messages * update nix config * show parse errors * error texts, simplexmq * alert messages * simplexmq, alert * better parsing * better parsing * simplify * correct message * remove test api * do not check size twice, bot types * send error in relays * do not create error item in relays * diff --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> |
||
|
|
1428ad75f9 |
core: channel comments preference (#6780)
* core: channel comments preference * api * remove from all group prefs * rename * fix api docs/types --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> |