These are issue candidates found in the codebase that are not already covered in GITHUB_ISSUES.md.
| # | Title | Difficulty | Labels | Why it matters | Evidence |
|---|---|---|---|---|---|
| 1 | Production deployment is localhost-locked | Hard | frontend, backend, deployment, api, bug, important |
The frontend API base and the backend CORS allowlist are both hardcoded to local origins, so a hosted frontend cannot reliably talk to the API without code changes. | frontend/js/config.js, frontend/js/chat.js, backend/app.py |
| 2 | Demo login ships as a client-side bypass | Easy | frontend, security, bug, important |
The auth page pre-fills demo credentials and the login handler short-circuits demo@bibliodrift.com into a fake local session without hitting the backend. | frontend/pages/auth.html, frontend/js/app.js |
| 3 | Normal login does not persist a JWT token | Medium | frontend, auth, bug, important |
Successful login stores the user and isLoggedIn, but not a token. The session restore code expects bibliodrift_token, so reload-based auth cannot work. |
frontend/js/app.js, frontend/js/app.js |
| 4 | Session verification calls a missing backend route | Medium | frontend, backend, auth, bug |
verifyStoredAuthSession() calls /api/v1/auth/verify, but the backend only exposes register/login/logout routes, so normal session verification returns 404 instead of validating the session. |
frontend/js/app.js, backend/app.py, backend/app.py |
| 5 | Auth verification keeps stale cached state on network errors | Medium | frontend, auth, bug |
If verification throws, the catch block returns the stored user instead of clearing auth state. That can leave the UI showing a logged-in state even when the server cannot be reached. | frontend/js/app.js |
| 6 | Library sync crashes on first use | Easy | backend, api, bug, important |
The sync handler iterates and sanitizes raw_items, but only items was defined from the request payload. That makes bulk sync fail immediately. |
backend/app.py, backend/app.py, backend/app.py |
| 7 | AI blurbs are cached without prompt context | Medium | backend, ai, db, bug |
Cached blurbs are keyed only by title and author, so the same book can reuse an old blurb even if the description, vibe, or prompt changes. | backend/app.py, backend/ai_service.py |
| 8 | Fallback blurbs get cached as if they were AI output | Medium | backend, ai, db, bug |
When the LLM is unavailable, fallback descriptions are still inserted into BookNote. That can permanently poison the cache with non-AI content. |
backend/app.py, backend/ai_service.py |
| 9 | BookNote cache table has no uniqueness constraint | Medium | backend, db, bug |
BookNote only has an index on title/author, not a uniqueness constraint. Duplicate rows can accumulate and .first() can return an arbitrary stale note. |
backend/models.py, backend/models.py, backend/app.py |
| 10 | Chat page overrides the API base to localhost | Easy | frontend, backend, deployment, bug |
The chat page hardcodes window.MOOD_API_BASE to localhost, so the chat feature breaks on any non-local deployment even if the shared config is updated. |
frontend/pages/chat.html |
| 11 | Library page has malformed duplicated controls markup | Easy | frontend, ui, bug |
The library hero contains two nested .sort-controls wrappers, which is invalid structure and can break layout or accessibility semantics. |
frontend/pages/library.html, frontend/pages/library.html |
| 12 | Backend app file contains duplicated route blocks | Hard | backend, maintainability, bug, important |
The module has repeated copies of core handlers later in the file, which creates drift risk and makes future fixes easy to apply to only one copy. | backend/app.py, backend/app.py, backend/app.py |
| # | Title | Difficulty | Labels | Why it matters | Evidence |
|---|---|---|---|---|---|
| 13 | Search endpoint returns results without pagination | Easy | backend, api, performance, bug |
Mood search endpoint returns all matching books in one request. No limit enforcement could cause memory spikes or large JSON payloads crashing on slow networks. | backend/app.py |
| 14 | Empty search results page has no fallback UI | Easy | frontend, ui, ux |
When mood search returns zero results, the page shows nothing or a generic error. Should display helpful "no results" state with suggested searches or categories. | frontend/pages/index.html |
| 15 | Book image requests have no timeout | Easy | backend, api, resilience |
When fetching external book covers from Google Books API, requests hang indefinitely if the service is slow. Should enforce a 5-10 second timeout to prevent request queue buildup. | frontend/js/app.js |
| 16 | Email validation regex too permissive | Easy | backend, security, validation |
Backend email validation uses a loose regex that accepts invalid email patterns. Should use RFC 5322 standard or server-side confirmation via verification link. | backend/validators.py |
| 17 | Password reset endpoint missing entirely | Easy | backend, auth, feature-gap |
Users cannot reset forgotten passwords. No /api/v1/auth/reset-password endpoint exists, leaving locked-out users with no self-service recovery path. |
backend/app.py (search for "password" returns no reset logic) |
| # | Title | Difficulty | Labels | Why it matters | Evidence |
|---|---|---|---|---|---|
| 18 | Rate limiting not enforced on AI endpoints | Medium | backend, api, security, cost |
AI generation endpoints (/generate-note, /category-books) have no per-user or per-IP rate limits. Malicious users can spam LLM calls, exhausting quota and increasing costs. |
backend/app.py, backend/app.py |
| 19 | Library sync doesn't handle partial failures | Medium | backend, api, resilience |
If one book in a bulk sync fails validation, the entire sync request is rejected. Should apply a partial success pattern: sync valid books, skip invalid ones, return detailed error report. | backend/app.py |
| 20 | Missing database indexes on frequently queried columns | Medium | backend, db, performance |
Queries like BookNote.query.filter_by(book_title, book_author) scan the full table. Compound index missing causes slow mood searches on large libraries. |
backend/models.py, backend/app.py |
| 21 | AI vibe generation returns empty string on LLM errors | Medium | backend, ai, ux |
If LLM fails after retries, generateAIVibe() returns "" instead of a fallback vibe. Frontend then displays empty handwritten-note element, looking broken. |
backend/ai_service.py |
| 22 | No X-Frame-Options or CSP headers set | Medium | frontend, backend, security |
Frontend pages lack Content-Security-Policy and X-Frame-Options headers. Site is vulnerable to clickjacking and inline script injection attacks. | backend/app.py (missing header middleware) |
| # | Title | Difficulty | Labels | Why it matters | Evidence |
|---|---|---|---|---|---|
| 23 | Refresh token rotation not implemented | Hard | backend, auth, security |
JWT tokens are issued but not rotated. Long-lived tokens increase risk if a token is leaked or intercepted. Should implement sliding-window refresh token rotation. | backend/app.py |
| 24 | Library sync version conflicts resolved silently without user warning | Hard | backend, api, sync, data-loss-risk |
When backend detects version mismatch, conflicts are "resolved" by server-side decree without notifying the user which local changes were discarded. Users lose unsaved edits silently. | backend/app.py, frontend/js/app.js |
| 25 | Google Books API key baked into frontend config | Hard | frontend, backend, security, deployment |
If GOOGLE_API_KEY is defined, it's embedded in the front-end JavaScript (visible in network tab). Attackers can harvest the key and exceed rate limits or hijack search functionality. |
frontend/js/config.js, backend/app.py |
| 26 | Async LibraryManager initialization can race with page rendering | Hard | frontend, ui, timing-bug |
LibraryManager._initPromise is not awaited before rendering shelves. If backend sync completes while render is in progress, rendered books may be replaced mid-animation, causing flicker or crashes. |
frontend/js/app.js, frontend/js/app.js |
| 27 | Missing SQL injection prevention in custom query builders | Hard | backend, db, security |
Some endpoints accept user input for mood descriptions or search filters and interpolate them into queries without parameterization. Vulnerable to SQL injection if input validation is bypassed. | backend/app.py |