Stripe hosted Checkout forces an email field; the Payment Element on our
own page supports email='never'. Bot creates a Customer with no email
(metadata[order_key]) via a self-hosted pay page: Subscription
(default_incomplete) / PaymentIntent, client_secret served from a
backend endpoint (never in a URL per Stripe), Link disabled. The cus_
handle is the durable Stripe id; the bot returns a signed recovery
handle over it in OrderStatus.providerRef for the client to back up.
Cancellation is always an authenticated per-cus_ portal session reached
by order key or saved handle — the email-OTP login page is gone. Update
provider rules, recovery, tests, code locations, refs; new web tier.
The transport-verified Ed25519 signer key already uniquely identifies
and authenticates an order, so the separate client-generated orderId is
redundant. Remove it from the wire, DB, and recovery: orders are keyed
by order_key; signing becomes mandatory (no key = no order); the client
backs up only order_sk (order_key is its public part). Two Stripe steps
correlate by the shared signer key; Stripe client_reference_id=order_key.
Mermaid treats ';' as a statement separator, so message/note labels
containing it fail to parse. Replace with comma/em-dash in the three
affected sequence-diagram labels.
Model only the persisted order states (requesting/completed/failed;
client adds paid) instead of five machines of transient/derived states.
A badge is a row in a per-period ledger, not a machine; provider
subscription status is re-derived per request, not stored. Bot and
client persistence each shrink to two tables (orders + badges).
Update both v2 plans and the roles/e2e SVGs to match; drop the stale
five-machine states SVG.
On an incoming call the desktop window blinked continuously (FileNotFoundException
from SoundPlayer.start writing into a missing ...\Temp\simplex).
Root cause: Files.desktop top-level val initializers run in any process that
touches the facade class, including a transient second instance (which reaches
acquireSingleInstance -> dataDir). Two of them deleted shared state used by the
running primary:
- tmpDir had .also { deleteOnExit() } - the second instance's normal exit deleted
...\Temp\simplex, so the primary then failed to write call sounds/recordings.
- preferencesTmpDir had .also { deleteRecursively() } - the second instance's
<clinit> wiped configPath\tmp (same anti-pattern, firing even earlier).
Make both declarations pure and do the destructive cleanup in Main, past the
single-instance check, so only the owning instance performs it (preferencesTmpDir
kept early, before any settings write). The remaining val-initializer side effects
are idempotent creations (mkdirs) that destroy nothing and are left in place.
Wide images size their preview box with a fixed width of DEFAULT_MAX_IMAGE_WIDTH
(500dp). #7125 switched the box from .aspectRatio() to a fixed .height() computed
from that nominal width; on screens narrower than 500dp, .width(500dp) is clamped
to the available width but the fixed height is not, so the top-aligned FillWidth
image is shorter than its box, leaving an empty strip below.
Compute the height from the width actually granted via a small Modifier.layout so
it tracks the clamped width, restoring the self-correcting behaviour .aspectRatio()
had. coerceAtMost(w) keeps the box within its nominal width (and bounds the
unbounded intrinsic-measurement pass), and coerceAtLeast(0) mirrors what
Modifier.width()'s SizeNode does for a negative w on a tiny window - so both
dimensions stay in range and the #7123 Constraints overflow crash cannot recur.
* ui: what's new in 7.0 (#7265)
* docs: add Hosting your own Chat Relay guide (#7263)
* docs: add Hosting your own Chat Relay guide
* cli: run headless relay without a terminal
--headless (no -e) now runs via simplexChatCore instead of the terminal
UI, so the relay runs as a systemd service without a TTY (withTerminal
requires one). Drains the event queue logging only errors, and sets
stdout to line-buffering so logs reach the journal.
* docs/chat-relay: debounce service
* Apply suggestions from code review
Co-authored-by: Evgeny <evgeny@poberezkin.com>
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
* Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 47.9% (179 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/zh_Hant/
* Translated using Weblate (Turkish)
Currently translated at 63.0% (235 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/tr/
* Translated using Weblate (Indonesian)
Currently translated at 95.7% (357 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/id/
---------
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
Co-authored-by: Evgeny <evgeny@poberezkin.com>
Co-authored-by: HUGOALH <hugoalh@users.noreply.hosted.weblate.org>
Co-authored-by: Omer <abulomer2001@gmail.com>
Co-authored-by: Rafi <rafimuhmad90@protonmail.com>
* docs: add Hosting your own Chat Relay guide
* cli: run headless relay without a terminal
--headless (no -e) now runs via simplexChatCore instead of the terminal
UI, so the relay runs as a systemd service without a TTY (withTerminal
requires one). Drains the event queue logging only errors, and sets
stdout to line-buffering so logs reach the journal.
* docs/chat-relay: debounce service
* Apply suggestions from code review
Co-authored-by: Evgeny <evgeny@poberezkin.com>
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
getLoadedImage subsampled with an OR cap on the larger side, so tall
images (e.g. phone screenshots) were reduced far below the display size
and rendered blurry. Mirror Android's calculateInSampleSize (keep the
smaller side at the target) so previews stay sharp, and add a decoded-
pixel ceiling so extreme aspect ratios can't blow up decode memory.
* desktop: show startup errors in a copyable window instead of bare "Failed to launch JVM"
When any exception escapes main() before the app window appears - a missing
DLL, a failed migration, broken AWT init - the jpackage launcher shows only
"Failed to launch JVM" and the cause is recorded nowhere: the launcher runs
without a console, so stderr is lost. Every report in #4146 stalled on this.
Catch the error and show it in a native Win32 window laid out like a message
box: an error icon and message, two clickable report links (the GitHub issue
tracker and the support email) above a read-only selectable box with the stack
trace, and an OK button. The links are SS_NOTIFY statics opened with
ShellExecute (browser for the URL, mail client for the email). Native, not
Swing, because broken AWT initialization is one of the failure causes. On
Windows the process then exits cleanly so the launcher does not also show its
own box; on other systems the error is rethrown to stderr.
* docs: plan justifying desktop startup error window (#4146)
* desktop: bundle jdk.accessibility to fix "Failed to launch JVM" when assistive technologies are enabled (#4146)
The jlinked runtime shipped in desktop packages did not include the
jdk.accessibility module. On Windows, when Java Access Bridge is enabled
(jabswitch -enable, "Enable Java Access Bridge" in Ease of Access, or a
screen reader creating %USERPROFILE%\.accessibility.properties), AWT
throws AWTError "Assistive Technology not found:
com.sun.java.accessibility.AccessBridge" during Toolkit init, before any
window or log output, and the jpackage launcher reports "Failed to
launch JVM".
* docs: plan justifying jdk.accessibility fix for Windows JVM launch (#4146)
* desktop: bundle jdk.accessibility only when building the Windows package
* 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
* website: fix broken GitHub links for project files in docs
* website: fix broken links across docs and pages
Render glossary tooltips through the shared replaceLink transform so
their relative links become absolute site URLs instead of 404ing when
injected across pages; add the English-only routes (downloads, faq,
jobs, reproduce, security, transparency) to supportedRoutes so the
language switcher stops emitting href="undefined"; passthrough-copy
docs/guide/images, docs/guide/diagrams and docs/themes.
Fix the SIMPLEX.md p2p anchor typo and correct image paths in CLI,
the v0.4 blog post and the fr/pl translation docs to point at the
existing shared assets.
* docs: add name resolution setup to SMP server guide
* docs: link SMP server names section to public names overview
* link
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
* core, web: correctly process name verification for channels, show names in directory
* remove duplicate verification
* remove plan
* refactor
* remove comments
* stabilize tests
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
* Bound shared file URI copies
* test: cover multi-read path in bounded URI file copy
* android, desktop: bound URI copies by sender badge file limit
* android, desktop: show file-too-large alert on bounded URI copy overrun
---------
Co-authored-by: Paul Bottinelli <paul.bottinelli@trailofbits.com>