122 lines
7.6 KiB
Markdown
122 lines
7.6 KiB
Markdown
# 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.
|