step4-proxy-proof.mjs 4.6 KB

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