/** * GATE 10 — Signup and admin provision */ import { describe, it, before, after } from 'node:test'; import assert from 'node:assert/strict'; import { createApp } from '../../src/app.js'; import { useTempStore } from '../helpers.js'; import { config } from '../../src/config.js'; describe('tenancy', () => { let ctx; let server; let port; before(async () => { ctx = useTempStore(); const app = createApp({ load: false }); await new Promise((resolve) => { server = app.listen(0, '127.0.0.1', () => { port = server.address().port; resolve(); }); }); }); after(async () => { await new Promise((r) => server.close(r)); ctx.cleanup(); }); it('POST /zapier/v1/signup returns free plan + apiKey', async () => { const res = await fetch(`http://127.0.0.1:${port}/zapier/v1/signup`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: 'user@example.com', name: 'Self Serve Co', veraeUsername: 'selfuser', veraePassword: 'selfpass', }), }); assert.equal(res.status, 201); const body = await res.json(); assert.equal(body.tenant.plan, 'free'); assert.ok(body.apiKey.startsWith('zmw_')); }); it('enterprise without contract rejected', async () => { const res = await fetch(`http://127.0.0.1:${port}/zapier/v1/admin/tenants`, { method: 'POST', headers: { 'content-type': 'application/json', 'x-admin-secret': config.adminSecret, }, body: JSON.stringify({ name: 'Ent Co', plan: 'enterprise', veraeUsername: 'e', veraePassword: 'p', }), }); assert.equal(res.status, 400); const body = await res.json(); assert.equal(body.code, 'VALIDATION_ERROR'); }); it('admin list does not leak passwords', async () => { const create = await fetch(`http://127.0.0.1:${port}/zapier/v1/admin/tenants`, { method: 'POST', headers: { 'content-type': 'application/json', 'x-admin-secret': config.adminSecret, }, body: JSON.stringify({ name: 'Pro Co', plan: 'pro', veraeUsername: 'puser', veraePassword: 'ppass', }), }); assert.equal(create.status, 201); const res = await fetch(`http://127.0.0.1:${port}/zapier/v1/admin/tenants`, { headers: { 'x-admin-secret': config.adminSecret }, }); assert.equal(res.status, 200); const body = await res.json(); const json = JSON.stringify(body); assert.doesNotMatch(json, /ppass/); assert.doesNotMatch(json, /veraePassword/); }); });