7.6 KiB
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.
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, fallback ranges, Monal 6.4.21 release, Monal 6.4.21 text quotes, Monal 6.4.21 decrypted body.
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.