| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /**
- * Step 2 proof: magic-link email + SMS OTP on Doltgres.
- *
- * cd apps/api
- * BRIVEN_ENGINE_DATABASE_URL=postgres://postgres:devpass@127.0.0.1:5434/briven_engine?sslmode=disable \
- * BRIVEN_DATA_PLANE_URL=postgres://postgres:devpass@127.0.0.1:5434/postgres?sslmode=disable \
- * BRIVEN_AUTH_CORE_ENABLED=true BRIVEN_ENV=development \
- * bun scripts/step2-passwordless-proof.mjs
- */
- process.env.BRIVEN_AUTH_CORE_ENABLED = 'true';
- process.env.BRIVEN_ENV = 'development';
- process.env.BRIVEN_ENGINE_DATABASE_URL =
- process.env.BRIVEN_ENGINE_DATABASE_URL ??
- 'postgres://postgres:devpass@127.0.0.1:5434/briven_engine?sslmode=disable';
- process.env.BRIVEN_DATA_PLANE_URL =
- process.env.BRIVEN_DATA_PLANE_URL ??
- 'postgres://postgres:devpass@127.0.0.1:5434/postgres?sslmode=disable';
- const { ensureBrivenEngineDatabase } = await import(
- '../src/services/auth-core/ensure-db.ts'
- );
- const { initAuthCoreSdk } = await import('../src/services/auth-core/engine.ts');
- const {
- createPasswordlessCode,
- consumePasswordlessCode,
- } = await import('../src/services/auth-core/passwordless.ts');
- const { getEnginePool } = await import('../src/services/auth-core/db.ts');
- const projectId = 'p_step2_local';
- const email = `step2_${Date.now()}@example.com`;
- const phone = `+1555${String(Date.now()).slice(-7)}`;
- console.log('=== Phase 3: passwordless (email magic + SMS OTP) on Doltgres ===');
- console.log({ email, phone, projectId });
- const ensured = await ensureBrivenEngineDatabase();
- if (!ensured.ok) {
- console.error('FAIL ensure', ensured);
- process.exit(1);
- }
- const inited = await initAuthCoreSdk();
- if (!inited) {
- console.error('FAIL init');
- process.exit(1);
- }
- // ── Email: OTP + magic link ─────────────────────────────────────────
- const emailCreate = await createPasswordlessCode({
- email,
- projectId,
- flowType: 'USER_INPUT_CODE_AND_MAGIC_LINK',
- });
- console.log('email create', {
- status: emailCreate.status,
- channel: emailCreate.status === 'OK' ? emailCreate.channel : null,
- hasCode: emailCreate.status === 'OK' ? Boolean(emailCreate.userInputCode) : false,
- hasLink: emailCreate.status === 'OK' ? Boolean(emailCreate.linkCode) : false,
- delivery: emailCreate.status === 'OK' ? emailCreate.delivery : null,
- });
- if (emailCreate.status !== 'OK' || !emailCreate.userInputCode) {
- console.error('FAIL email create', emailCreate);
- process.exit(1);
- }
- // Wrong code
- const bad = await consumePasswordlessCode({
- preAuthSessionId: emailCreate.preAuthSessionId,
- deviceId: emailCreate.deviceId,
- userInputCode: '000000',
- projectId,
- });
- console.log('email wrong OTP', bad.status);
- if (bad.status === 'OK') {
- console.error('FAIL accepted wrong OTP');
- process.exit(1);
- }
- // Correct OTP
- const emailConsume = await consumePasswordlessCode({
- preAuthSessionId: emailCreate.preAuthSessionId,
- deviceId: emailCreate.deviceId,
- userInputCode: emailCreate.userInputCode,
- projectId,
- });
- console.log('email consume OTP', {
- status: emailConsume.status,
- userId: emailConsume.status === 'OK' ? emailConsume.user.id : null,
- createdNewUser:
- emailConsume.status === 'OK' ? emailConsume.createdNewUser : null,
- session:
- emailConsume.status === 'OK' ? emailConsume.session.handle : null,
- });
- if (emailConsume.status !== 'OK') {
- console.error('FAIL email consume', emailConsume);
- process.exit(1);
- }
- // Magic link path (fresh code)
- const emailCreate2 = await createPasswordlessCode({
- email: `step2link_${Date.now()}@example.com`,
- projectId,
- flowType: 'MAGIC_LINK',
- });
- if (emailCreate2.status !== 'OK' || !emailCreate2.linkCode) {
- console.error('FAIL magic create', emailCreate2);
- process.exit(1);
- }
- const linkConsume = await consumePasswordlessCode({
- preAuthSessionId: emailCreate2.preAuthSessionId,
- deviceId: emailCreate2.deviceId,
- linkCode: emailCreate2.linkCode,
- projectId,
- });
- console.log('email magic link consume', {
- status: linkConsume.status,
- userId: linkConsume.status === 'OK' ? linkConsume.user.id : null,
- });
- if (linkConsume.status !== 'OK') {
- console.error('FAIL magic consume', linkConsume);
- process.exit(1);
- }
- // ── SMS OTP ─────────────────────────────────────────────────────────
- const smsCreate = await createPasswordlessCode({
- phoneNumber: phone,
- projectId,
- flowType: 'USER_INPUT_CODE',
- });
- console.log('sms create', {
- status: smsCreate.status,
- channel: smsCreate.status === 'OK' ? smsCreate.channel : null,
- hasCode: smsCreate.status === 'OK' ? Boolean(smsCreate.userInputCode) : false,
- delivery: smsCreate.status === 'OK' ? smsCreate.delivery : null,
- });
- if (smsCreate.status !== 'OK' || !smsCreate.userInputCode) {
- console.error('FAIL sms create', smsCreate);
- process.exit(1);
- }
- const smsConsume = await consumePasswordlessCode({
- preAuthSessionId: smsCreate.preAuthSessionId,
- deviceId: smsCreate.deviceId,
- userInputCode: smsCreate.userInputCode,
- projectId,
- });
- console.log('sms consume', {
- status: smsConsume.status,
- userId: smsConsume.status === 'OK' ? smsConsume.user.id : null,
- phone: smsConsume.status === 'OK' ? smsConsume.user.phone : null,
- session: smsConsume.status === 'OK' ? smsConsume.session.handle : null,
- });
- if (smsConsume.status !== 'OK') {
- console.error('FAIL sms consume', smsConsume);
- process.exit(1);
- }
- // SQL proof
- const pool = getEnginePool();
- const users = await pool.query(
- `SELECT id, email, phone, tenant_id FROM be_users WHERE tenant_id LIKE 'proj-p-step2%' ORDER BY time_joined DESC LIMIT 10`,
- );
- const sessions = await pool.query(
- `SELECT session_handle, user_id FROM be_sessions WHERE user_id = ANY($1::text[])`,
- [
- [
- emailConsume.user.id,
- linkConsume.user.id,
- smsConsume.user.id,
- ],
- ],
- );
- const leftoverCodes = await pool.query(
- `SELECT COUNT(*)::int AS n FROM be_passwordless_codes`,
- );
- console.log('SQL users', users.rows);
- console.log('SQL sessions for step2 users', sessions.rowCount);
- console.log('leftover codes (should be 0 used ones gone)', leftoverCodes.rows[0]);
- console.log('');
- console.log('✔ PHASE 3 LOCAL PROOF OK (passwordless)');
- console.log(' storage: Doltgres');
- console.log(' email OTP: OK');
- console.log(' email magic link: OK');
- console.log(' SMS OTP: OK (delivery mode log/provider)');
- console.log(' wrong OTP rejected: OK');
- console.log(' sessions created: OK (handle = cookie)');
- process.exit(0);
|