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 библиотеку
43 lines
3.9 KiB
JavaScript
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');
|
|
});
|