# Quoted replies — 2026-10-08 The operator approved package 8 and rollout after package 7. Sol High is retained; no delegation. Existing blunix handoff edits (177 lines) remain unstaged. Baseline release is generation 555, client `f6feaa7`. ## Representation decision XEP-0461 0.2.1 selects origin-id/message-id for direct messages and the room-issued stanza-id for group messages. MAM cursor IDs are separate. Replies carry a sender-scoped navigation hint; lookup never crosses a conversation/account, and omitted-sender ID collisions are unresolved. Fallback quotes use XEP-0428 codepoint counts, not UTF-16 string lengths. Stored quote snapshots survive missing/edited history without pretending to identify a different original. An existing edit can be quoted with the original ID; navigation displays its current saved version. Legacy OMEMO still encrypts a UTF-8 string, now including the quoted prefix and answer. There is no new cryptographic payload/namespace. The outer body is content-independent. Reply ID/address and fallback range stay outside encryption; reply linkage and quote length are visible metadata. Quote text is never put there. The web client applies ranges after decryption only; for encrypted messages only an actual quoted prefix may be separated. Metadata is not authenticated and is used only as a navigation hint. Quoted encrypted originals fail closed if encryption is unavailable. The operator reports **Monal Stable 6.4.21**. Public Monal source uses plain `> ` text quotes and displays decrypted text as the body. Structured reply support is still an [open upstream feature](https://github.com/monal-im/Monal/issues/1671). Exact release mapping: Stable merge **`9be038e9`**, subject `6.4.21 (#1650)`, also tag `Build_iOS_1092`. Its `chatViewController.m` Quote action prefixes each selected line with `> ` and adds an empty line; `MLMessageProcessor.m` uses decrypted text as body without reply/fallback handling. Both exact 6.4.21 files were inspected, after checking develop and oldstable/6.4-line. Source evidence is not physical-client acceptance. Sources: [reply IDs/fallback](https://xmpp.org/extensions/xep-0461.html), [fallback ranges](https://xmpp.org/extensions/xep-0428.html), [Monal 6.4.21 release](https://github.com/monal-im/Monal/commit/9be038e9268cc7c6aa57be0a3958cafddfe8e39f), [Monal 6.4.21 text quotes](https://github.com/monal-im/Monal/blob/9be038e9268cc7c6aa57be0a3958cafddfe8e39f/Monal/Classes/chatViewController.m), [Monal 6.4.21 decrypted body](https://github.com/monal-im/Monal/blob/9be038e9268cc7c6aa57be0a3958cafddfe8e39f/Monal/Classes/MLMessageProcessor.m). ## Implementation and checks Explicit Reply, composer preview/Cancel/Escape, draft snapshot persistence, focus return, same-chat jump/highlight, local missing-history status and 44px controls are implemented. Group reflections add their room stanza ID to an existing local echo. No database migration/dependency/server change. Checks: zero svelte-check errors/warnings, **74 passing tests** and production build. Tests exercise Unicode fallback, bad ranges/senders, group IDs vs archive IDs, ambiguous/cross-chat lookup, encrypted deferred parsing, draft restart/cancel/send races and real Double Ratchet/AES-GCM round trip of the complete quote. Wire XML contains neither original nor answer text; the legacy decoder receives the expected quoted text. The first candidate exposed a real Svelte-proxy/IndexedDB clone failure on reply-draft restart. Draft persistence and send capture now take a plain state snapshot; the restart regression passes in both engines. Candidate Chromium `state-chromium-1791411343829` and WebKit `state-webkit-1791411434234` pass `QUOTED-REPLIES`: actual encrypted A/B send, zero quote/answer text in wire XML, Unicode, restart/settings/chat isolation/cancel focus, failed send retained, carbon/archive reload without duplication, focused original navigation, missing local history, an original outside the latest 60-message page, room-stamped group references and 44px/no-overflow layouts at 320/402/740/1280. Zero page errors. WebKit reading anchors/pagination/late sizing and draft-send races also pass. Its additional phone-menu check initially ran before roster-supplied actions were ready; the runner now waits for the contact Call control before checking menu order. Focused WebKit `state-webkit-1791411540489` passes all phone controls (menu/modal focus, themes, safe-area layouts and large text), zero page errors. Production source did not change for that fixture correction. Chromium `state-chromium-1791411605534` passes phone controls, reading anchors, draft-send races, actual closed-profile offline history/draft recovery and Retry (47 ms first socket, 292 ms online), zero page errors. Linux WebKit's fully offline cold-start limitation remains; actual offline coverage uses Chromium. The physical iPhone screen background remains operator-confirmed from package 7, not a new simulation claim. Final candidate JS `assets/index-DlzpKHNm.js`, SHA-256 `44b6735197c887591b15a7a87c7b1b196872f73347a6cec4ef5b7b5d8ad7a335`. A separate candidate run sent the operator one original and one quoted answer from the existing audit account, both verified as legacy encrypted stanzas with no original/answer text in outer XML. The operator explicitly confirmed on **Monal Stable 6.4.21**: “Ja, beides einmal lesbar” for the quoted original and the answer. This is actual encrypted PWA → Monal display acceptance; Monal's own text-only replies remain the documented readable fallback without structured original navigation. No personal- account/device changes. ## Release and live evidence Client **`8ea43b9`** is pushed to main, pinned by the isolated blunix **`084f7fa`** lock commit pushed to capability-layout. Switch succeeded as **generation 556**, system `/nix/store/q06xgjsnkc4k1r0y9xx3cib0v4dwv3nk-nixos-system-blunix-26.11.20260910.8ce4ef6`; nginx root `/nix/store/8r40d45r1g73cr1mv55xa9jsglybslbx-0ff-chat-0.1.0`. Candidate, store and HTTPS JS hashes match. Worker is unchanged: `e28aaebf01c98e3252e29968a67f1bc8896518e465682f7dc54b3b2f06e85a06`. HTTPS 200, revalidation/Vary and unchanged strict CSP verified; iPhone translucent-status metadata is retained. Only nginx restarted; all ten checked platform services are active, zero failed units. Rollback: **555**, preserving phone/background and reconnect fixes. Existing 177 blunix handoff additions remain unstaged. The local preview is stopped. Live Chromium `state-chromium-1791412183448` passes matching HTTPS bundle/CSP and the full quoted-reply flow (encrypted direct, group, drafts, original/missing/older-history navigation and phone layouts), zero page errors. Retry opens a socket in 48 ms and is online in 204 ms. The first live run's expiry-only query-error fixture was healed by asynchronous freshness updates, so no send error occurred. The final fixture uses an explicit empty list for a known encrypted peer, fails closed, and restores its exact saved cache row before recovery; real ratchets/keys are untouched. Live WebKit `state-webkit-1791412474302` passes matching HTTPS bundle/CSP, phone controls and the full quoted-reply flow, zero page errors. A preceding run passed all assertions but recorded `Context is stopped`; its historical report is retained. The final repeat did not reproduce it; error source and stack capture were added to the runner without filtering errors or changing the deployed client. All 19 owned audit rooms are confirmed absent; local seed fixtures were removed and the preview remains stopped. Actual Monal acceptance is recorded above; VoiceOver/keyboard/touch ergonomics and fully offline Linux WebKit remain separate checks/limitations. Package 9 still requires its own encrypted-attachment interoperability design.