import { test } from 'node:test'; import assert from 'node:assert/strict'; import { createApp } from '../src/index.js'; async function startServer() { const port = 30000 + Math.floor(Math.random() * 10000); const app = createApp({ port, baseUrl: `http://127.0.0.1:${port}`, dbPath: ':memory:', cleanupIntervalMs: 3_600_000 }); await new Promise((r) => app.server.listen(port, r)); return { app, baseUrl: `http://127.0.0.1:${port}` }; } const ROOM_PAYLOAD = { title: '1C <-> app integration contract', goal: 'Agree endpoints, schedule, auth', participants: [ { role: 'windows-1c', knows: ['IIS', '1C', 'Windows logs'], needs_to_determine: ['frequency'] }, { role: 'application', knows: ['app code'], needs_to_determine: ['contract'] }, ], }; test('HTTP integration: create -> markdown invite -> negotiate -> finalize -> final.md', async () => { const { app, baseUrl } = await startServer(); try { // 1. agent reads the machine-readable instruction page const doc = await (await fetch(`${baseUrl}/create.md`)).text(); assert.match(doc, /POST .*\/api\/rooms/); // 2. creates the room const created = (await (await fetch(`${baseUrl}/api/rooms`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(ROOM_PAYLOAD), })).json()) as any; assert.equal(created.invite_urls.length, 2); const [aUrl, bUrl] = created.invite_urls; const tokenA = aUrl.split('/').pop(); const tokenB = bUrl.split('/').pop(); const auth = { authorization: `Bearer ${tokenA}` }; const authB = { authorization: `Bearer ${tokenB}`, 'content-type': 'application/json' }; const H = { ...auth, 'content-type': 'application/json' }; // 3. agent B opens its invite URL markdown representation const inviteMd = await (await fetch(`${bUrl}.md`)).text(); assert.match(inviteMd, /AI Rendezvous/); assert.match(inviteMd, /application/); // 4. A states facts await fetch(`${baseUrl}/api/rooms/${created.room_id}/messages`, { method: 'POST', headers: H, body: JSON.stringify({ content: 'IIS exposes /exchange/hs with basic auth.' }) }); // 5. B asks a blocking question const q = (await (await fetch(`${baseUrl}/api/rooms/${created.room_id}/questions`, { method: 'POST', headers: authB, body: JSON.stringify({ question: 'Check IIS logs for the last 7 days: which endpoints were actually called and how often?', blocking: true, addressed_to_participant_id: created.participants[0].id }), })).json()) as any; assert.equal(q.status, 'open'); // 6. room view tells A what to do next const viewA = (await (await fetch(`${baseUrl}/api/rooms/${created.room_id}`, { headers: auth })).json()) as any; assert.equal(viewA.your_role, 'windows-1c'); assert.match(viewA.what_you_should_do_next, /blocking question/i); assert.ok(Array.isArray(viewA.available_actions) && viewA.available_actions.length > 0); // 7. A verifies and resolves await fetch(`${baseUrl}/api/rooms/${created.room_id}/messages`, { method: 'POST', headers: H, body: JSON.stringify({ content: 'IIS logs: /exchange/hs called every 15 min by svc_exchange.' }) }); await fetch(`${baseUrl}/api/rooms/${created.room_id}/questions/${q.id}/resolve`, { method: 'POST', headers: H, body: JSON.stringify({ resolution: 'Verified in IIS logs: /exchange/hs, every 15 minutes.' }) }); // 8. B proposes contract, both agree await fetch(`${baseUrl}/api/rooms/${created.room_id}/contract`, { method: 'PUT', headers: authB, body: JSON.stringify({ markdown: '## Facts\n- /exchange/hs every 15 min\n## Interface\nPOST /exchange/hs\n## Authentication\nBasic auth\n## Error handling\nHTTP 5xx -> retry 3x\n## Unresolved\nnone' }), }); const agree1 = (await (await fetch(`${baseUrl}/api/rooms/${created.room_id}/agree`, { method: 'POST', headers: authB, body: '{}' })).json()) as any; assert.equal(agree1.room_status, 'open'); const agree2 = (await (await fetch(`${baseUrl}/api/rooms/${created.room_id}/agree`, { method: 'POST', headers: H, body: '{}' })).json()) as any; assert.equal(agree2.room_status, 'agreed'); // 9. final markdown artifact const final = await (await fetch(`${baseUrl}/api/rooms/${created.room_id}/final.md`, { headers: auth })).text(); assert.match(final, /Agreed Contract/); assert.match(final, /exchange\/hs/); // 10. token isolation: tokenB cannot use room of another room; forged token rejected const forged = await fetch(`${baseUrl}/api/rooms/${created.room_id}`, { headers: { authorization: 'Bearer nope' } }); assert.equal(forged.status, 403); // room id without token -> forbidden const noToken = await fetch(`${baseUrl}/api/rooms/${created.room_id}`); assert.equal(noToken.status, 403); } finally { app.close(); } }); test('HTTP: cannot read room by id without token; unknown routes 404; human pages render', async () => { const { app, baseUrl } = await startServer(); try { const created = (await (await fetch(`${baseUrl}/api/rooms`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(ROOM_PAYLOAD), })).json()) as any; // observer URL: read-only view with turn indicator assert.ok(created.observer_url, 'createRoom must return observer_url'); const obs = await fetch(created.observer_url); assert.equal(obs.status, 200); const obsHtml = await obs.text(); assert.match(obsHtml, /observer/i); assert.match(obsHtml, /Whose turn/); const obsMd = await (await fetch(`${created.observer_url}.md`)).text(); assert.match(obsMd, /Whose turn/); // observer token must NOT work as a participant token const obsToken = created.observer_url.split('/').pop(); const write = await fetch(`${baseUrl}/api/rooms/${created.room_id}/messages`, { method: 'POST', headers: { authorization: `Bearer ${obsToken}`, 'content-type': 'application/json' }, body: JSON.stringify({ content: 'hi' }), }); assert.equal(write.status, 403); // wrong observer token -> forbidden assert.equal((await fetch(`${baseUrl}/o/${created.room_id}/nope`)).status, 403); // observer HTML highlights whose turn it is after a blocking question appears const pidA = created.participants[0].id; const tokB = created.invite_urls[1].split('/').pop(); // before join: observer turn waits on B joining const obsHtml0 = await (await fetch(created.observer_url)).text(); assert.match(obsHtml0, /invite not confirmed/); // B reports taking the room into work const j = await (await fetch(`${baseUrl}/api/rooms/${created.room_id}/join`, { method: 'POST', headers: { authorization: `Bearer ${tokB}` }, })).json(); assert.equal((j as any).joined, true); await fetch(`${baseUrl}/api/rooms/${created.room_id}/questions`, { method: 'POST', headers: { authorization: `Bearer ${tokB}`, 'content-type': 'application/json' }, body: JSON.stringify({ question: 'verify X on your side', blocking: true, addressed_to_participant_id: pidA }), }); const obsHtml2 = await (await fetch(created.observer_url)).text(); assert.match(obsHtml2, /turn-role/); assert.match(obsHtml2, /windows-1c/); const r = await fetch(`${baseUrl}/api/rooms/${created.room_id}`); assert.equal(r.status, 403); const r2 = await fetch(`${baseUrl}/api/rooms/${created.room_id}?token=${created.participants[0].token}`); assert.equal(r2.status, 200); const r3 = await fetch(`${baseUrl}/api/nosuch`); assert.equal(r3.status, 404); const html = await (await fetch(`${baseUrl}/create`)).text(); assert.match(html, /AI Rendezvous/); const landing = await (await fetch(baseUrl)).text(); assert.match(landing, /Meet\. Verify\. Agree\. Disappear\./); assert.match(landing, /How it works/); const llms = await (await fetch(`${baseUrl}/llms.txt`)).text(); assert.match(llms, /^# http/ms); assert.match(llms, /\/api\/rooms/); assert.match(llms, /what_you_should_do_next/); // canonical security policy served; short version referenced everywhere agents read const sec = await (await fetch(`${baseUrl}/security.md`)).text(); assert.match(sec, /control plane/); assert.match(sec, /SECRET_TRANSFER_REQUIRED/); assert.match(llms, /security\.md/); const createMd = await (await fetch(`${baseUrl}/create.md`)).text(); assert.match(createMd, /security\.md/); assert.match(createMd, /SECRET_TRANSFER_REQUIRED/); const roomHtml = await (await fetch(created.invite_urls[0])).text(); assert.match(roomHtml, /windows-1c/); const health = await (await fetch(`${baseUrl}/health`)).json(); assert.ok(health.ok); // any member can destroy (checked last — it deletes the room) const del = await fetch(`${baseUrl}/api/rooms/${created.room_id}`, { method: 'DELETE', headers: { authorization: `Bearer ${obsToken}` }, }); assert.equal(del.status, 200); assert.equal( (await fetch(`${baseUrl}/api/rooms/${created.room_id}`, { headers: { authorization: `Bearer ${created.participants[0].token}` } })).status, 404, ); // forged token cannot destroy const c2 = (await (await fetch(`${baseUrl}/api/rooms`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(ROOM_PAYLOAD), })).json()) as any; assert.equal( (await fetch(`${baseUrl}/api/rooms/${c2.room_id}`, { method: 'DELETE', headers: { authorization: 'Bearer nope' } })).status, 403, ); // participant can destroy via the UI form endpoint const uiDel = await fetch(`${c2.invite_urls[0]}/destroy`, { method: 'POST' }); assert.equal(uiDel.status, 200); assert.match(await uiDel.text(), /destroyed/i); } finally { app.close(); } });