coulomb-social/scripts/owner_communication/browser.mjs
tegwick cb9301537e
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 6m57s
Exercise actual communication owner sources through isolated browser flows
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-30 21:51:36 +01:00

123 lines
6 KiB
JavaScript

import assert from 'node:assert/strict';
import { pathToFileURL } from 'node:url';
const [portal, fixtures, receiver, modulePath] = process.argv.slice(2);
const allowed = new Set([portal, fixtures, receiver]);
for (const base of allowed) {
const url = new URL(base);
assert.equal(url.hostname, '127.0.0.1');
assert.equal(url.protocol, 'http:');
}
const { chromium } = await import(pathToFileURL(modulePath).href);
const browser = await chromium.launch({ headless: true });
let outside = 0;
const context = await browser.newContext({ serviceWorkers: 'block' });
await context.route('**/*', route => {
if (!allowed.has(new URL(route.request().url()).origin)) {
outside += 1;
return route.abort();
}
return route.continue();
});
const page = await context.newPage();
page.setDefaultTimeout(15000);
const request = async (method, url, options = {}) => {
assert(allowed.has(new URL(url).origin));
return context.request[method](url, { ...options, maxRedirects: 0 });
};
const state = async () => (await request('get', fixtures + '/state')).json();
const control = async (path, data = {}) => {
const response = await request('post', fixtures + path, { data });
assert.equal(response.status(), 200);
};
async function register(name) {
await page.goto(portal + '/register');
await page.getByLabel('Username', { exact: true }).fill(name);
await page.getByLabel('Email', { exact: true }).fill(name + '@example.test');
await page.getByRole('button', { name: 'Send verification email' }).click();
await page.getByText('Check your email', { exact: false }).first().waitFor();
await page.goto(fixtures + '/mailbox');
const body = await page.locator(`article[data-recipient="${name}@example.test"]`).innerText();
const url = body.match(/http:\/\/127\.0\.0\.1:\d+\/registration\/verify\?handle=[A-Za-z0-9_-]+/)[0];
assert.equal(new URL(url).origin, portal);
return url;
}
async function consume(url, button, accepted) {
assert.equal(new URL(url).origin, portal);
await page.goto(url);
const response = page.waitForResponse(r => r.url().startsWith(portal + '/registration/')
&& r.request().method() === 'POST');
await page.getByRole('button', { name: button, exact: true }).click();
const result = await response;
assert.equal(result.status() < 400, accepted);
}
try {
const verified = await register('verified.person');
assert.equal((await state()).provisions, 0); // mail receipt alone cannot provision
assert.equal((await state()).users, 1); // only the synthetic inviter exists
const wrongCaller = await request('post', receiver + '/v1/registration-verifications/consume',
{ headers: { Authorization: 'Bearer synthetic-other-caller-token' },
data: { handle: new URL(verified).searchParams.get('handle') } });
assert.equal(wrongCaller.status(), 400);
await consume(verified, 'Verify and continue', true);
const passwordLink = page.getByRole('link', { name: 'Create password', exact: true });
assert.equal(await passwordLink.count(), 1, await page.locator('body').innerText());
assert.equal((await state()).provisions, 1);
assert.equal((await state()).users, 2);
await consume(verified, 'Verify and continue', false);
const canceled = await register('canceled.person');
await consume(canceled.replace('/verify?', '/cancel?'), 'Cancel registration', true);
await consume(canceled, 'Verify and continue', false);
const expired = await register('expired.person');
await control('/expire', { email: 'expired.person@example.test' });
await consume(expired, 'Verify and continue', false);
assert.equal((await state()).provisions, 1);
const headers = { Authorization: 'Bearer synthetic-user-engine-mail-token' };
const challenge = { registration_id: 'reg-wrong-binding',
normalized_email: 'denied@example.test', preferred_username: 'denied.person',
client_id: 'coulomb-social-test', tenant: 'tenant:communication-test', correlation_id: 'test' };
for (const bad of [{ tenant: 'tenant:other' }, { client_id: 'client-other' }]) {
const response = await request('post', receiver + '/v1/registration-verifications',
{ headers, data: { ...challenge, ...bad } });
assert.equal(response.status(), 400);
}
const missingCaller = await request('post', receiver + '/v1/registration-verifications',
{ headers: { Authorization: 'Bearer invalid-caller-token' }, data: challenge });
assert.equal(missingCaller.status(), 401);
assert.equal((await state()).messages, 3);
// Synthetic preauthenticated MFA session; real portal form and role/CSRF checks.
await context.addCookies([{ name: 'ue_session', value: 'synthetic-admin-session',
url: portal, httpOnly: true, sameSite: 'Lax' }]);
assert.equal((await request('get', portal + '/admin/tenant%3Aother')).status(), 403);
const admin = portal + '/admin/tenant%3Acommunication-test';
await page.goto(admin);
const form = page.locator('form[action$="/invitations"]');
await form.getByLabel('Email', { exact: true }).fill('invited@example.test');
await form.getByRole('button', { name: 'Send invitation', exact: true }).click();
await control('/deliver');
assert.equal((await state()).messages, 4);
await control('/deliver');
assert.equal((await state()).messages, 4);
await page.reload();
await page.getByRole('button', { name: 'Resend', exact: true }).click();
await control('/deliver');
assert.equal((await state()).messages, 5);
await control('/suppress', { email: 'suppressed@example.test' });
await page.goto(admin);
await form.getByLabel('Email', { exact: true }).fill('suppressed@example.test');
await form.getByRole('button', { name: 'Send invitation', exact: true }).click();
await control('/deliver');
assert.equal((await state()).messages, 5);
assert.equal((await state()).provisions, 1);
assert.equal(outside, 0);
console.log(JSON.stringify({ passed: true, browser_requests_outside_fixture: outside,
registration_verify_cancel_expire_replay: true, mailbox_not_authorization: true,
tenant_client_caller_denials: true, real_invitation_and_resend: true,
duplicate_delivery_and_suppression: true, provider_calls: 5 }));
} finally {
await browser.close();
}