Conversation
…gration Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AX5fZLCKjxyASaMAxMxxum
…Turso)
Phase 0: swap the DB access mechanism only — business logic, schema, and the
OLX collection method are unchanged. libSQL is SQLite-compatible (single code
path: file: locally, Turso URL in prod), enabling Render + Turso deploy.
- db.ts: createClient + initDb (executeMultiple schema.sql) + thin async
helpers dbGet/dbAll/dbRun; drop the historical migration scaffold
(addColumnIfMissing/migrateListingsTable/backfill/PRAGMA/WAL) — schema.sql
already holds every column.
- env.ts: load server/.env before db.ts reads TURSO_* (imported first in db.ts).
- Whole DB layer is async: every .get/.all/.run -> await dbGet/dbAll/dbRun;
interactive db.transaction('write') for read->decide->write (upsert,
statusEngine, analysis/relevance/aiPicks commit); db.batch('write') for pure
write sets (cascade delete, sort swaps, filtered_out recompute, migratePostedAt).
- index.ts: host 0.0.0.0, CORS origin from WEB_ORIGIN, await initDb before listen.
- CLI entrypoints (scan.ts, migratePostedAt.ts) call initDb.
- .env.example: TURSO_DATABASE_URL/TURSO_AUTH_TOKEN/WEB_ORIGIN.
- docs: architecture.md/structure.md updated; render-turso-phase0.md marked done.
Verified locally against libSQL file:: build green; /health ok; live OLX scan
(GraphQL) -> upsert+dedup; coverage-window disable; manual PATCH override;
CLI scan; cascade-delete/recompute via batch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AX5fZLCKjxyASaMAxMxxum
Beginner-friendly walkthrough: Turso DB setup, Render Web Service (backend) with build/start commands and env vars, Render Static Site (frontend) with /api/* rewrite (same-origin, no CORS), verification, free-tier cold-start notes, and troubleshooting. No code changes — frontend keeps relative /api fetch; the Render rewrite proxies it to the backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AX5fZLCKjxyASaMAxMxxum
Gate access to the dashboard behind Google login (allowlist of one email) without turning the app multi-user — no users table, no user_id, no data partitioning. Auth is a lock on the front door plus a session cookie. Server (server/src/auth/): - config.ts: env (GOOGLE_CLIENT_ID/ALLOWED_EMAILS/SESSION_SECRET), cookie flags (prod cross-site Secure+SameSite=None, local http Lax), fail-fast assertAuthConfigured, AUTH_DISABLED dev bypass. - plugin.ts: fastify-plugin (non-encapsulated) registering @fastify/cookie and @fastify/jwt, verifyGoogleIdToken via google-auth-library, global onRequest lock on /api/* (skips /health, /api/auth/*, CORS preflight). - routes.ts: POST /api/auth/google, GET /api/auth/me, POST /api/auth/logout. - index.ts: import ./env first, assertAuthConfigured, CORS credentials, register auth before domain routes. Frontend (web/src/auth/): - useAuth.ts: useSession/useLogin/useLogout, reacts to global 401 event. - AuthGate.tsx: login screen with GoogleLogin, wraps the app. - base.ts: credentials: 'include', VITE_API_BASE prefix, 401 -> gate event. - main.tsx: GoogleOAuthProvider. Header: logout button. DB schema untouched. Docs + .env examples updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015wZmcZ6mmoQa5rv9gCa1KX
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Що це
Замок доступу до дашборду через Google-логін — пускає лише власника (allowlist email у
.env). Це НЕ перехід у мультикористувацький режим: жодної таблиціusers, жодногоuser_idу даних, single-user інваріант із CLAUDE.md лишається. OAuth тут — замок на вході + сесійна httpOnly-кукі.План:
docs/plans/google-oauth-gate.md.Потік
@react-oauth/google) → Google ID-token.POST /api/auth/google { credential }→ сервер верифікує (google-auth-library,aud+email_verified), звіряє зALLOWED_EMAILS.olx_session. Інакше403.onRequest-замок на/api/*(крім/api/auth/*,/health) →401без валідної кукі.GET /api/auth/me→200показує застосунок,401→ гейт. Будь-який 401 від API повертає на гейт.Зміни
Сервер (
server/src/auth/):config.ts(env + кукі-флаги + fail-fast),plugin.ts(fastify-plugin, non-encapsulated;@fastify/cookie+@fastify/jwt;verifyGoogleIdToken; глобальний замок),routes.ts(/api/auth/google|me|logout).index.ts:import './env'першим,assertAuthConfigured(), CORScredentials:true, auth до доменних роутів.Фронт (
web/src/auth/):useAuth.ts(useSession/useLogin/useLogout, реакція на подію 401),AuthGate.tsx(екран входу).base.ts:credentials:'include'+VITE_API_BASE+ подія 401.main.tsx:GoogleOAuthProvider. Header: кнопка «Вийти».Схема БД не чіпається. Оновлено
docs/architecture.md,docs/structure.md,.env.example(server + web).Деплой (Render, cross-site)
Фронт і API на різних доменах → кукі
Secure+SameSite=None, CORS з явнимWEB_ORIGIN. Потрібен OAuth Client ID у Google Cloud Console (Authorized JavaScript origins = домен фронта +http://localhost:5173). Env:GOOGLE_CLIENT_ID,ALLOWED_EMAILS,SESSION_SECRET,AUTH_COOKIE_SECURE=true,VITE_GOOGLE_CLIENT_ID,VITE_API_BASE.Перевірено
npm run build(server tsc + web tsc/vite) — зелений.AUTH_DISABLED=true→/api/projects200(без регресу); auth on →/health200,/api/projects401,/api/auth/me401,/api/auth/googleбез тіла400, зі сміттєвим токеном401; відсутні ключі → fail-fast при старті.🤖 Generated with Claude Code
Generated by Claude Code