feat: auth, persistence, and AI integration

- Cookie-based auth via backend proxy (httpOnly JWTs)
- Supabase Postgres persistence for sessions/messages/profiles + RLS
- Fix cross-user session leak (token cache keyed by full token, not 50-char prefix)
- Fix missing table grants (42501) via migration; auto-provision profiles on user creation
- Chat validation, ownership checks, rate limiting, /api/chat/sessions route ordering
- Frontend auth-state reset + credentials include
- OpenRouter AI provider (OpenAI-compatible base URL, reasoning disabled)
- Tests: chatValidation, appState
This commit is contained in:
2026-08-19 09:41:40 -04:00
parent 93a35a7343
commit ff9da4d324
43 changed files with 4174 additions and 249 deletions
+119
View File
@@ -0,0 +1,119 @@
/* ──────────────────────────────────────────
Sign-In Modal — padhle
────────────────────────────────────────── */
.signin-overlay {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.45);
z-index: 10000;
backdrop-filter: blur(4px);
}
.signin-card {
background: var(--color-surface-lowest, #fff);
border-radius: 16px;
padding: 40px 36px;
width: 100%;
max-width: 400px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
.signin-title {
font-family: var(--font-heading);
font-size: 1.5rem;
font-weight: 700;
color: var(--color-on-surface);
margin: 0 0 6px;
}
.signin-subtitle {
font-size: 0.9rem;
color: var(--color-on-surface-variant);
margin: 0 0 28px;
}
.signin-form {
display: flex;
flex-direction: column;
gap: 16px;
}
.signin-label {
font-size: 0.82rem;
font-weight: 600;
color: var(--color-on-surface);
margin-bottom: 4px;
}
.signin-input {
width: 100%;
padding: 10px 14px;
border: 1px solid #d1d5db;
border-radius: 8px;
font-size: 0.95rem;
font-family: var(--font-body);
color: var(--color-on-surface);
background: var(--color-surface-lowest);
outline: none;
transition: border-color 0.2s;
}
.signin-input:focus {
border-color: var(--color-primary, #000);
}
.signin-btn {
margin-top: 8px;
padding: 12px;
background: var(--color-primary, #000);
color: var(--color-on-primary, #fff);
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
font-family: var(--font-body);
cursor: pointer;
transition: opacity 0.2s;
}
.signin-btn:hover:not(:disabled) {
opacity: 0.9;
}
.signin-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.signin-footer {
margin-top: 20px;
font-size: 0.88rem;
color: var(--color-on-surface-variant);
text-align: center;
}
.signin-link {
background: none;
border: none;
color: var(--color-primary, #000);
font-weight: 600;
font-family: var(--font-body);
cursor: pointer;
text-decoration: underline;
}
.signin-link:hover {
text-decoration: none;
}
.signin-note {
margin-top: 16px;
font-size: 0.75rem;
color: var(--color-on-surface-variant);
text-align: center;
opacity: 0.7;
}