step4-proxy-proof.mjs154 lines · main
| 1 | /** |
| 2 | * Step 4 proof: first-party proxy keeps cookies on the **app** host. |
| 3 | * |
| 4 | * Spins up: |
| 5 | * - "API" Hono with real Doltgres briven-engine FDI |
| 6 | * - "App" Hono with /api/auth/* proxy → API FDI |
| 7 | * Client hits App only; expects Set-Cookie + successful signup. |
| 8 | * |
| 9 | * cd apps/api |
| 10 | * BRIVEN_ENGINE_DATABASE_URL=postgres://postgres:devpass@127.0.0.1:5434/briven_engine?sslmode=disable \ |
| 11 | * BRIVEN_DATA_PLANE_URL=postgres://postgres:devpass@127.0.0.1:5434/postgres?sslmode=disable \ |
| 12 | * bun scripts/step4-proxy-proof.mjs |
| 13 | */ |
| 14 | |
| 15 | process.env.BRIVEN_AUTH_CORE_ENABLED = 'true'; |
| 16 | process.env.BRIVEN_ENV = 'development'; |
| 17 | process.env.BRIVEN_ENGINE_DATABASE_URL = |
| 18 | process.env.BRIVEN_ENGINE_DATABASE_URL ?? |
| 19 | 'postgres://postgres:devpass@127.0.0.1:5434/briven_engine?sslmode=disable'; |
| 20 | process.env.BRIVEN_DATA_PLANE_URL = |
| 21 | process.env.BRIVEN_DATA_PLANE_URL ?? |
| 22 | 'postgres://postgres:devpass@127.0.0.1:5434/postgres?sslmode=disable'; |
| 23 | process.env.BRIVEN_API_ORIGIN = 'http://127.0.0.1:3011'; |
| 24 | process.env.BRIVEN_WEB_ORIGIN = 'http://127.0.0.1:3010'; |
| 25 | |
| 26 | import { Hono } from 'hono'; |
| 27 | |
| 28 | const { ensureBrivenEngineDatabase } = await import( |
| 29 | '../src/services/auth-core/ensure-db.ts' |
| 30 | ); |
| 31 | const { initAuthCoreSdk } = await import('../src/services/auth-core/engine.ts'); |
| 32 | const { authCoreFdiRouter } = await import('../src/routes/auth-core-fdi.ts'); |
| 33 | const { proxyBrivenEngineAuth, appAuthPathToFdiSuffix } = await import( |
| 34 | '../../../packages/auth/src/engine/proxy.ts' |
| 35 | ); |
| 36 | |
| 37 | console.log('=== Step 4: first-party proxy (cookies on app host) ==='); |
| 38 | |
| 39 | if (!(await ensureBrivenEngineDatabase()).ok) { |
| 40 | console.error('FAIL ensure DB'); |
| 41 | process.exit(1); |
| 42 | } |
| 43 | if (!(await initAuthCoreSdk())) { |
| 44 | console.error('FAIL init'); |
| 45 | process.exit(1); |
| 46 | } |
| 47 | |
| 48 | // Unit-ish path mapping |
| 49 | const mapped = appAuthPathToFdiSuffix('/api/auth/signup'); |
| 50 | console.log('path map /api/auth/signup →', mapped); |
| 51 | if (mapped !== '/signup') { |
| 52 | console.error('FAIL path map'); |
| 53 | process.exit(1); |
| 54 | } |
| 55 | |
| 56 | // API server (briven-engine FDI) |
| 57 | const api = new Hono(); |
| 58 | api.route('/', authCoreFdiRouter); |
| 59 | const apiServer = Bun.serve({ |
| 60 | port: 3011, |
| 61 | fetch: api.fetch, |
| 62 | }); |
| 63 | console.log('API on', apiServer.url.href); |
| 64 | |
| 65 | // App server (first-party proxy) |
| 66 | const app = new Hono(); |
| 67 | app.all('/api/auth/*', async (c) => { |
| 68 | const res = await proxyBrivenEngineAuth(c.req.raw, { |
| 69 | apiOrigin: 'http://127.0.0.1:3011', |
| 70 | projectId: 'p_step4_local', |
| 71 | proxyMount: '/api/auth', |
| 72 | }); |
| 73 | return res; |
| 74 | }); |
| 75 | app.get('/health', (c) => c.json({ app: true })); |
| 76 | const appServer = Bun.serve({ |
| 77 | port: 3010, |
| 78 | fetch: app.fetch, |
| 79 | }); |
| 80 | console.log('APP on', appServer.url.href); |
| 81 | |
| 82 | const email = `step4_${Date.now()}@example.com`; |
| 83 | const password = 'Step4Test!Pass99'; |
| 84 | |
| 85 | // Client talks ONLY to app host |
| 86 | const res = await fetch('http://127.0.0.1:3010/api/auth/signup', { |
| 87 | method: 'POST', |
| 88 | headers: { |
| 89 | 'content-type': 'application/json', |
| 90 | 'x-briven-project-id': 'p_step4_local', |
| 91 | }, |
| 92 | body: JSON.stringify({ |
| 93 | formFields: [ |
| 94 | { id: 'email', value: email }, |
| 95 | { id: 'password', value: password }, |
| 96 | ], |
| 97 | }), |
| 98 | }); |
| 99 | |
| 100 | const body = await res.json().catch(() => ({})); |
| 101 | const setCookies = |
| 102 | typeof res.headers.getSetCookie === 'function' |
| 103 | ? res.headers.getSetCookie() |
| 104 | : [res.headers.get('set-cookie')].filter(Boolean); |
| 105 | |
| 106 | console.log('proxy signup status', res.status); |
| 107 | console.log('proxy body status', body.status); |
| 108 | console.log('x-briven-proxy', res.headers.get('x-briven-proxy')); |
| 109 | console.log('set-cookie count', setCookies.length); |
| 110 | console.log( |
| 111 | 'set-cookie sample', |
| 112 | setCookies.map((c) => String(c).slice(0, 40) + '…'), |
| 113 | ); |
| 114 | |
| 115 | const ok = |
| 116 | res.status === 200 && |
| 117 | body.status === 'OK' && |
| 118 | res.headers.get('x-briven-proxy') === 'first-party' && |
| 119 | setCookies.length >= 1 && |
| 120 | setCookies.some((c) => String(c).includes('sAccessToken')); |
| 121 | |
| 122 | // Sign-in through proxy too |
| 123 | const res2 = await fetch('http://127.0.0.1:3010/api/auth/signin', { |
| 124 | method: 'POST', |
| 125 | headers: { |
| 126 | 'content-type': 'application/json', |
| 127 | 'x-briven-project-id': 'p_step4_local', |
| 128 | }, |
| 129 | body: JSON.stringify({ |
| 130 | formFields: [ |
| 131 | { id: 'email', value: email }, |
| 132 | { id: 'password', value: password }, |
| 133 | ], |
| 134 | }), |
| 135 | }); |
| 136 | const body2 = await res2.json().catch(() => ({})); |
| 137 | console.log('proxy signin status', res2.status, body2.status); |
| 138 | |
| 139 | apiServer.stop(); |
| 140 | appServer.stop(); |
| 141 | |
| 142 | if (!ok || body2.status !== 'OK') { |
| 143 | console.error('FAIL step 4', { ok, body, body2 }); |
| 144 | process.exit(1); |
| 145 | } |
| 146 | |
| 147 | console.log(''); |
| 148 | console.log('✔ STEP 4 PROOF OK'); |
| 149 | console.log(' client hit: http://127.0.0.1:3010/api/auth/* (app host)'); |
| 150 | console.log(' upstream: http://127.0.0.1:3011/v1/auth-core/fdi/* (API)'); |
| 151 | console.log(' Set-Cookie returned on app response: yes'); |
| 152 | console.log(' signup + signin via proxy: OK'); |
| 153 | console.log(' storage still Doltgres (via API)'); |
| 154 | process.exit(0); |