Files
LumaWeb/experiments/0002-xmpp-library/selection-spike/test/extensions.test.mjs
T
wt 51a414d386 S00-003: Evaluate Stanza with verified SCRAM and bounded WSS ingress
Changes: Propose the pinned XMPP library decision and add an isolated browser-built selection spike combining reviewed public SASL, SHA-512 and parser seams. Exercise TLS/xmpp handshake, strongest compatible non-PLUS authentication, rejected unsafe paths and extension mappings; document duplicate-body export projection and remaining limits. Preserve dependency notices, evidence and QA handoff.
Validation: Clean-cache pinned npm ci succeeded; npm test passed 112 checks; check-dependencies.py verified 51 locked entries, 26 installed packages and 340 unchanged vendor files; make check passed 72 tooling tests. No actual browser runtime, independent full XMPP server/client or production encryption/release readiness claim.

Task: S00-003
Agent: auto-protocol-f474114f0168
Role: protocol
Action: claim
Status: review

Task title: Проверить XMPP WSS/auth библиотеку
2026-10-15 18:20:05 +07:00

43 lines
3.9 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {Client, importMessage, attribute, text} from '../dist/browser.mjs';
const client=new Client();
const roundtrip=(kind,xml)=>{
const imported=importMessage(xml,client.stanzas,{});
assert.equal(imported.kind,kind);
// The API exposes both a selected body and the full language collection.
// For this fixture choose the language collection as the sole export input;
// passing both representations concatenates text in Stanza 12.22.1.
const output = {...imported.stanza};
if (output.archive?.item?.message) {
output.archive = {...output.archive, item: {...output.archive.item, message: {...output.archive.item.message}}};
delete output.archive.item.message.body;
}
const emitted=client.stanzas.export(kind,output).toString();
const again=importMessage(emitted,client.stanzas,{}).stanza;
return {stanza:imported.stanza,again,emitted};
};
for(const [name,kind,xml,check] of [
['MAM result/forwarded stable IDs','message','<message xmlns="jabber:client"><result xmlns="urn:xmpp:mam:2" id="archive-1" queryid="query-1"><forwarded xmlns="urn:xmpp:forward:0"><message xmlns="jabber:client" id="message-1"><body>synthetic</body><origin-id xmlns="urn:xmpp:sid:0" id="origin-1"/></message></forwarded></result></message>',s=>{assert.equal(s.archive.id,'archive-1');assert.equal(s.archive.item.message.originId,'origin-1');assert.equal(s.archive.item.message.body,'synthetic');}],
['MUC join','presence','<presence xmlns="jabber:client" to="room@conference.example.invalid/user"><x xmlns="http://jabber.org/protocol/muc"/></presence>',s=>assert.equal(s.muc.type,'join')],
['Jingle signaling','iq','<iq xmlns="jabber:client" type="set" id="call-1"><jingle xmlns="urn:xmpp:jingle:1" action="session-terminate" sid="session-1"><reason><success/></reason></jingle></iq>',s=>{assert.equal(s.jingle.action,'session-terminate');assert.equal(s.jingle.sid,'session-1');}],
['HTTP upload slot','iq','<iq xmlns="jabber:client" type="result" id="upload-1"><slot xmlns="urn:xmpp:http:upload:0"><put url="https://upload.example.invalid/put"/><get url="https://upload.example.invalid/get"/></slot></iq>',s=>{assert.equal(s.httpUpload.download,'https://upload.example.invalid/get');}],
['legacy opaque OMEMO encoding','message','<message xmlns="jabber:client"><encrypted xmlns="eu.siacs.conversations.axolotl"><header sid="1"><key rid="2">AA==</key><iv>AA==</iv></header><payload>AA==</payload></encrypted></message>',s=>{assert.equal(s.omemo.header.sid,1);assert.equal(s.omemo.header.keys[0].rid,2);assert.equal(s.omemo.payload.toString('hex'),'00');}]
]) test(`${name}: real registry import/export`,()=>{const r=roundtrip(kind,xml);check(r.stanza);check(r.again);});
test('public plugin registry supports future opaque extension without vendor patch',()=>{
// Deliberately NOT a claimed OMEMO2 wire implementation or encryption result.
client.use(c=>c.stanzas.define({namespace:'urn:luma:selection-spike:opaque',element:'opaque',
path:'message.spikeOpaque',fields:{id:attribute('id'),value:text()}}));
const r=roundtrip('message','<message xmlns="jabber:client"><opaque xmlns="urn:luma:selection-spike:opaque" id="fixture-1">synthetic-data</opaque></message>');
assert.deepEqual(r.stanza.spikeOpaque,{id:'fixture-1',value:'synthetic-data'});
assert.deepEqual(r.again.spikeOpaque,r.stanza.spikeOpaque);
const wrong=importMessage('<message xmlns="jabber:client"><opaque xmlns="urn:luma:wrong" id="fixture-1">ignored</opaque></message>',client.stanzas,{});
assert.equal(wrong.stanza.spikeOpaque,undefined);
});
test('record raw dual-body export behavior requiring explicit projection',()=>{
const r=importMessage('<message xmlns="jabber:client"><body>synthetic</body></message>',client.stanzas,{});
const raw=client.stanzas.export('message',r.stanza).toString();
assert.equal(importMessage(raw,client.stanzas,{}).stanza.body,'syntheticsynthetic');
});