f7519d36f0
Task 9.5: /health now reports the egress provider backing each channel (sandbox vs http). scripts/smoke-capability.mjs proves the slice end to end: sandbox egress SENT through the broker; EMAIL routed to the env-gated HttpProvider and actually delivered to a LOCAL echo server (real egress, no external network, no credentials); idempotent replay; /health bindings. App wires CapabilityModule. P9 slice-1 verification: 103 tests green, pnpm -r build all packages+demos, boundary clean, capability smoke PASS, all prior smokes (realtime/inbox/support/ adapter/route/ai/calendar) still PASS through the broker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
3.2 KiB
JavaScript
62 lines
3.2 KiB
JavaScript
// P9 slice-1 smoke: the Capability Broker as governed egress.
|
|
// (a) sandbox egress SENT via the broker (WEBHOOK, no network);
|
|
// (b) REAL egress via the env-gated HttpProvider → a LOCAL echo server (EMAIL);
|
|
// (c) idempotent replay; (d) /health shows provider bindings.
|
|
// Requires the service started with IIOS_PROVIDER_URL_EMAIL=http://127.0.0.1:4599/echo.
|
|
import 'dotenv/config';
|
|
import http from 'node:http';
|
|
import jwt from 'jsonwebtoken';
|
|
|
|
const SERVICE = process.env.SMOKE_URL ?? 'http://localhost:3200';
|
|
const APP_ID = 'portal-demo';
|
|
const APP_SECRET = JSON.parse(process.env.APP_SECRETS ?? '{"portal-demo":"dev-secret"}')[APP_ID];
|
|
const token = jwt.sign({ sub: 'egress', appId: APP_ID, orgId: `org_${APP_ID}` }, APP_SECRET, { algorithm: 'HS256', expiresIn: '1h' });
|
|
const assert = (c, m) => { if (!c) { console.error('✗', m); process.exit(1); } console.log('✓', m); };
|
|
|
|
async function send(channelType, target, payload, idempotencyKey) {
|
|
const r = await fetch(`${SERVICE}/v1/adapters/${channelType}/send`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
body: JSON.stringify({ target, payload, idempotencyKey }),
|
|
});
|
|
if (!r.ok) throw new Error(`send ${channelType} ${r.status}: ${await r.text()}`);
|
|
return r.json();
|
|
}
|
|
|
|
// Local echo server the real HttpProvider will POST to (no external network).
|
|
const received = [];
|
|
const echo = http.createServer((req, res) => {
|
|
let b = '';
|
|
req.on('data', (c) => (b += c));
|
|
req.on('end', () => { try { received.push(JSON.parse(b || '{}')); } catch { received.push({}); } res.writeHead(200, { 'content-type': 'application/json' }); res.end('{"ok":true}'); });
|
|
});
|
|
await new Promise((r) => echo.listen(4599, '127.0.0.1', r));
|
|
|
|
try {
|
|
// (a) sandbox egress through the broker
|
|
const sandboxCmd = await send('WEBHOOK', 'user@x', { text: 'hi via broker' }, `cap-sb-${Date.now()}`);
|
|
assert(sandboxCmd.status === 'SENT' && String(sandboxCmd.providerRef).startsWith('sim-'), 'sandbox egress SENT through the broker (no network)');
|
|
|
|
// (b) real egress via env-gated HttpProvider → local echo server
|
|
const before = received.length;
|
|
const httpCmd = await send('EMAIL', 'buyer@yamuna', { text: 'real egress proof' }, `cap-http-${Date.now()}`);
|
|
assert(httpCmd.status === 'SENT' && String(httpCmd.providerRef).startsWith('http-'), 'EMAIL egress routed to the real HttpProvider');
|
|
assert(received.length === before + 1, 'local echo server actually received the POST (real egress, no external network)');
|
|
assert(received[received.length - 1]?.payload?.text === 'real egress proof', 'echo received the exact payload');
|
|
|
|
// (c) idempotent replay → one command
|
|
const key = `cap-idem-${Date.now()}`;
|
|
const a = await send('EMAIL', 'buyer@yamuna', { text: 'x' }, key);
|
|
const b = await send('EMAIL', 'buyer@yamuna', { text: 'x' }, key);
|
|
assert(a.id === b.id, 'idempotent replay → one command');
|
|
|
|
// (d) /health shows provider bindings
|
|
const health = await (await fetch(`${SERVICE}/health`)).json();
|
|
assert(health.egressProviders?.EMAIL === 'http' && health.egressProviders?.WEBHOOK === 'sandbox', '/health shows EMAIL=http, WEBHOOK=sandbox bindings');
|
|
|
|
console.log('\nP9 capability smoke: PASS');
|
|
} finally {
|
|
echo.close();
|
|
}
|
|
process.exit(0);
|