feat(xmpp): natieve calls F3 — persistente XMPP-sessie met resource-binding #1128

Merged
brenno merged 6 commits from feat/native-calls-f3-muc into main 2026-08-02 15:07:41 +00:00
Owner

Fase F3.1 van de natieve-calls-functie (docs/design/NATIVE_CALLS.md §5): een persistente XMPP-sessie met resource-binding die de F2 XmppConnection opvolgt. Dit is de primitief onder de rest van F3 — MUC (XEP-0045, de Jitsi-conferentiekamer én OciDecks companion-kamer §5.1) en later Jingle rijden hierop.

Wat

XmppSession.connect() voert dezelfde bewezen auth uit als F2 (open→features→SASL; SCRAM > PLAIN alleen als NetGuard.maySendReusableSecret klaart > ANONYMOUS; <see-other-host> fail-closed geweigerd; SCRAM mutual-auth met constant-time server-signature-vergelijking), maar sluit niet af: het herstart de stream, bindt een resource (RFC 6120 §7) en blijft open — inkomende stanza's naar stanzas, versturen via sendStanza, tot close().

Supersedeert F2's eenmalige XmppConnection (verwijderd): een sessie die meteen na connect() sluit ís de oude "test connection", dus één primitief i.p.v. twee — geen gedupliceerde, security-kritische auth. Getypeerde XmppSessionResult/XmppSessionFailure (code, geen proza; de UI mapt naar l10n).

De test-verbinding-dialoog opent nu een volledige sessie (auth + bind) en toont bij succes de gebonden full-JID ("Sessie actief als …") naast het mechanisme; hij sluit de sessie meteen weer en bewaart niets.

Waarborgen

  • Reviews, beide GO: beveiligingsarchitect (de vier auth-invarianten trouw overgezet uit F2; fail-closed opruiming op élke faalroute; DTD/XXE-weigering intact op het nieuwe live-pad; geen nieuwe egress) en kernwaardenbewaker ("bewaart niets" klopt nog; layering; supersede-besluit verdedigbaar). Twee review-punten doorgevoerd: een live stream-drop-signaal (sluit stanzas, zodat de MUC-slice een done-signaal krijgt en sendStanza niet op een dode transport schrijft) en een preciezere serverRedirect-code voor een post-auth <see-other-host>.
  • Geen nieuwe egress: reuse van F2's socket-gepinde openXmppFrameTransport. Geen nieuwe dependency, geen pubspec/SBOM-wijziging.
  • Tests (13, fake-transport, geen socket): de F2-auth-cases (RFC 5802-vector, mechanisme-voorkeur, mutual-auth-weigering, see-other-host, verse nonce) + resource-bind-succes/-weigering + live inbound/outbound-dispatch + server-stream-drop + live-DTD-drop (XXE-probe gedropt, sessie blijft levend).
  • Docs: SOURCE_MAP (xmpp_session vervangt xmpp_connection; dialoog-entry bijgewerkt). l10n: 2 nieuwe strings × 31 talen.

Poortstand (eerlijk)

make check is groen op alle statische poorten én op alle F3-eigen tests. In de volledige suite staan 3 tests rood, alle geërfd en byte-identiek aan origin/main (F3 raakt geen van de bronbestanden):

  • chrome_no_fixed_white_surface_test + ui_text_scale_test — #1124-welcome-redesign (lib/widgets/shell/welcome_screen.dart), apart in behandeling (codex/fix-welcome-screen-gates);
  • docs_anchor_links_test — een gebroken kop-anker in docs/CHECKS.md (#forgejoworkflowslinux-gateyml…) uit de CI-docs-wijzigingen (#1123/#1127).

Dit is de gedocumenteerde main-drift (de volledige suite is niet per-PR gepoort; #1127 zet nu een volle-poort-op-push op main). F3 verandert die rode stand niet.

Fase F3.1 van de natieve-calls-functie (`docs/design/NATIVE_CALLS.md` §5): een **persistente XMPP-sessie met resource-binding** die de F2 `XmppConnection` opvolgt. Dit is de primitief onder de rest van F3 — MUC (XEP-0045, de Jitsi-conferentiekamer én OciDecks companion-kamer §5.1) en later Jingle rijden hierop. ## Wat `XmppSession.connect()` voert dezelfde **bewezen** auth uit als F2 (open→features→SASL; SCRAM > PLAIN alleen als `NetGuard.maySendReusableSecret` klaart > ANONYMOUS; `<see-other-host>` fail-closed geweigerd; SCRAM mutual-auth met constant-time server-signature-vergelijking), maar sluit niet af: het **herstart de stream, bindt een resource** (RFC 6120 §7) en blijft **open** — inkomende stanza's naar `stanzas`, versturen via `sendStanza`, tot `close()`. **Supersedeert** F2's eenmalige `XmppConnection` (verwijderd): een sessie die meteen na `connect()` sluit ís de oude "test connection", dus één primitief i.p.v. twee — geen gedupliceerde, security-kritische auth. Getypeerde `XmppSessionResult`/`XmppSessionFailure` (code, geen proza; de UI mapt naar l10n). De test-verbinding-dialoog opent nu een volledige sessie (auth + bind) en toont bij succes de **gebonden full-JID** ("Sessie actief als …") naast het mechanisme; hij sluit de sessie meteen weer en bewaart niets. ## Waarborgen - **Reviews, beide GO**: beveiligingsarchitect (de vier auth-invarianten trouw overgezet uit F2; fail-closed opruiming op élke faalroute; DTD/XXE-weigering intact op het nieuwe live-pad; geen nieuwe egress) en kernwaardenbewaker ("bewaart niets" klopt nog; layering; supersede-besluit verdedigbaar). Twee review-punten doorgevoerd: een **live stream-drop-signaal** (sluit `stanzas`, zodat de MUC-slice een done-signaal krijgt en `sendStanza` niet op een dode transport schrijft) en een preciezere `serverRedirect`-code voor een post-auth `<see-other-host>`. - **Geen nieuwe egress**: reuse van F2's socket-gepinde `openXmppFrameTransport`. Geen nieuwe dependency, geen pubspec/SBOM-wijziging. - **Tests** (13, fake-transport, geen socket): de F2-auth-cases (RFC 5802-vector, mechanisme-voorkeur, mutual-auth-weigering, see-other-host, verse nonce) + resource-bind-succes/-weigering + live inbound/outbound-dispatch + server-stream-drop + live-DTD-drop (XXE-probe gedropt, sessie blijft levend). - **Docs**: SOURCE_MAP (`xmpp_session` vervangt `xmpp_connection`; dialoog-entry bijgewerkt). l10n: 2 nieuwe strings × 31 talen. ## Poortstand (eerlijk) `make check` is groen op **alle statische poorten** én op **alle F3-eigen tests**. In de volledige suite staan 3 tests rood, alle **geërfd** en byte-identiek aan `origin/main` (F3 raakt geen van de bronbestanden): - `chrome_no_fixed_white_surface_test` + `ui_text_scale_test` — #1124-welcome-redesign (`lib/widgets/shell/welcome_screen.dart`), apart in behandeling (`codex/fix-welcome-screen-gates`); - `docs_anchor_links_test` — een gebroken kop-anker in `docs/CHECKS.md` (`#forgejoworkflowslinux-gateyml…`) uit de CI-docs-wijzigingen (#1123/#1127). Dit is de gedocumenteerde main-drift (de volledige suite is niet per-PR gepoort; #1127 zet nu een volle-poort-op-push op main). F3 verandert die rode stand niet.
XmppSession voert dezelfde bewezen auth uit als F2 (open→features→SASL,
SCRAM>PLAIN-wss-gated>ANONYMOUS, see-other-host-weigering), maar sluit
niet af: het herstart de stream, bindt een resource (RFC 6120 §7) en
blijft OPEN — inkomende stanza's naar `stanzas`, versturen via
`sendStanza`, tot `close`. Dit is de persistente primitief onder MUC
(volgende slice) en het companion-kanaal (§5.1).

Supersedeert F2's eenmalige XmppConnection: een sessie die meteen na
connect() sluit ís de oude 'test connection', dus één primitief i.p.v.
twee (geen gedupliceerde, security-kritische auth). Getypeerde
XmppSessionResult/-Failure (code, geen proza). 12 tests: de F2-auth-cases
+ bind-succes/-weigering + live inbound/outbound-dispatch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
De dialoog opent nu een volledige XmppSession (auth + resource-bind) en
sluit die meteen weer; bij succes toont hij de gebonden full-JID naast
het mechanisme. Bewaart nog steeds niets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Opvolging van de beveiligingsarchitect- en bewaker-review:
- Live drain-modus seint nu stream-einde/-fout door: XmppSession sluit
  `stanzas` en zet _live=false, zodat de MUC-slice (die op stanzas de
  kamer-levensduur rijdt) een done-signaal krijgt en sendStanza niet op
  een dode transport blijft schrijven. Test: server-drop eindigt de stream.
- Post-auth <see-other-host> krijgt de precieze serverRedirect-code
  i.p.v. generiek resourceBindFailed (blijft fail-closed; _BindException
  draagt nu de faalcode).
- Live-DTD-drop nu getest (XXE-probe wordt gedropt, sessie blijft levend);
  rauwe NUL-bytes in de PLAIN-vector als \u0000-escape.
- SOURCE_MAP:1015 (dialoog-entry) bijgewerkt: XmppConnection→XmppSession,
  resource-binding + 'Sessie actief als' (bewaker-bevinding).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Twee nieuwe d()-bronstrings uit xmpp_test_connection_dialog.dart: de
'Sessie actief als'-label voor de gebonden sessie-JID en de
resource-binding-foutmelding. Alle 31 niet-Nederlandse talen gevuld via
make add-l10n; make l10n-check groen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
style(xmpp): dart format F3
Some checks failed
scans / scans (pull_request) Has been cancelled
static-gate / static-gate (pull_request) Has been cancelled
8705b22629
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit e104061b99 into main 2026-08-02 15:07:41 +00:00
Sign in to join this conversation.
No description provided.