fix(auth): enterprise SSO bcrypt hash + upgrade cost 10→12
- Enterprise SAML/OIDC callbacks used raw 'sso_xxx' string as passwordHash which would crash bcrypt.compare(). Now uses userRepo.hashPassword(randomUUID()) - Added updateLastLogin() for existing enterprise SSO users - Upgraded bcrypt cost factor from 10 to 12 per PRD spec - All 53 auth tests passing
This commit is contained in:
parent
0c4e53a0ed
commit
b0e1a54481
@ -7,18 +7,23 @@ description: Refresh the Windsurf chat history archive (re-scan all repos, updat
|
||||
Refreshes the centralized Windsurf chat history archive at `__LOCAL_LLMs/AI_IDE_CHAT_HISTORY/WINDSURF/`.
|
||||
Auto-discovers new repos, updates symlinks, and re-copies docs + workflows.
|
||||
|
||||
## Covered Repos (All 8 workspaces)
|
||||
## Covered Repos (All 13 workspaces)
|
||||
|
||||
| Repo | Product | Workflows | Docs |
|
||||
| ----------------------------------- | ---------------- | --------- | ---- |
|
||||
| `learning_voice_ai_agent` | LysnrAI | ✅ | ✅ |
|
||||
| `learning_multimodal_memory_agents` | MindLyst | ✅ | ✅ |
|
||||
| `learning_ai_clock` | ChronoMind | ✅ | — |
|
||||
| `learning_ai_peakpulse` | PeakPulse | ✅ | — |
|
||||
| `learning_ai_fastgap` | NomGap | ✅ | — |
|
||||
| `learning_ai_jarvis_jr` | JarvisJr | ✅ | — |
|
||||
| `learning_ai_common_plat` | Common Platform | ✅ | — |
|
||||
| `learning_agent_monitoring_fx` | Agent Monitoring | ✅ | — |
|
||||
| Repo | Product | Workflows | Docs |
|
||||
| ----------------------------------- | ------------------ | --------- | ---- |
|
||||
| `learning_ai_common_plat` | Common Platform | ✅ | ✅ |
|
||||
| `learning_voice_ai_agent` | LysnrAI | ✅ | ✅ |
|
||||
| `learning_multimodal_memory_agents` | MindLyst | ✅ | ✅ |
|
||||
| `learning_ai_clock` | ChronoMind | ✅ | — |
|
||||
| `learning_ai_fastgap` | NomGap | ✅ | — |
|
||||
| `learning_ai_jarvis_jr` | JarvisJr | ✅ | — |
|
||||
| `learning_ai_peakpulse` | PeakPulse | ✅ | — |
|
||||
| `learning_ai_notes` | NoteLett | ✅ | — |
|
||||
| `learning_ai_flowmonk` | FlowMonk | ✅ | — |
|
||||
| `learning_ai_trails` | ActionTrail | ✅ | — |
|
||||
| `learning_ai_smart_auth` | SmartAuth | ✅ | — |
|
||||
| `learning_ai_auth_app` | ByteLyst Auth | ✅ | — |
|
||||
| `learning_ai_productivity_web` | Productivity Tools | ✅ | — |
|
||||
|
||||
## Steps
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ echo "✨ All repos pushed!"
|
||||
## What it does:
|
||||
|
||||
1. **Backup** — creates timestamped backup branches, cleans up old ones (7 days), skips duplicates
|
||||
2. **Push** — pushes `main` to `origin/main` for all 7 repos
|
||||
2. **Push** — pushes `main` to `origin/main` for all 13 repos
|
||||
|
||||
## Repositories:
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Push local main branch to origin for all 7 workspace repos
|
||||
description: Push local main branch to origin for all 13 workspace repos
|
||||
---
|
||||
|
||||
# Push Repos
|
||||
@ -18,7 +18,7 @@ done < ~/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt
|
||||
|
||||
## What it does:
|
||||
|
||||
1. Iterates over all 7 workspace repos
|
||||
1. Iterates over all 13 workspace repos
|
||||
2. Runs `git push origin main` in each
|
||||
3. Fails fast if a repo has diverged from remote (resolve with rebase manually)
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Pull latest from origin main across all 7 workspace repos
|
||||
description: Pull latest from origin main across all 13 workspace repos
|
||||
---
|
||||
|
||||
# Sync Repos
|
||||
@ -18,7 +18,7 @@ done < ~/code/mygh/learning_ai_common_plat/.windsurf/workflows/repos.txt
|
||||
|
||||
## What it does:
|
||||
|
||||
1. Iterates over all 7 workspace repos
|
||||
1. Iterates over all 13 workspace repos
|
||||
2. Runs `git pull --ff-only origin main` in each
|
||||
3. Fails fast if there are local divergent commits (use `git pull --rebase` manually in that case)
|
||||
|
||||
|
||||
@ -11,3 +11,7 @@ learning_ai_jarvis_jr
|
||||
learning_ai_peakpulse
|
||||
learning_ai_notes
|
||||
learning_ai_flowmonk
|
||||
learning_ai_trails
|
||||
learning_ai_smart_auth
|
||||
learning_ai_auth_app
|
||||
learning_ai_productivity_web
|
||||
|
||||
@ -45,6 +45,10 @@ All code across the ByteLyst workspace repos:
|
||||
- learning_ai_jarvis_jr (JarvisJr)
|
||||
- learning_ai_peakpulse (PeakPulse)
|
||||
- learning_ai_notes (NoteLett)
|
||||
- learning_ai_trails (ActionTrail)
|
||||
- learning_ai_smart_auth (SmartAuth)
|
||||
- learning_ai_auth_app (ByteLyst Auth)
|
||||
- learning_ai_productivity_web (Productivity Tools)
|
||||
|
||||
## Domain Context
|
||||
|
||||
@ -52,7 +56,7 @@ This is a multi-product ecosystem with shared platform services. Key architectur
|
||||
|
||||
- **Platform services** (Fastify 5, TypeScript ESM) provide auth, telemetry, feature flags, etc.
|
||||
- **Shared packages** (@bytelyst/\*) eliminate duplication across products
|
||||
- **Product backends** handle domain-specific logic (port 4010-4017)
|
||||
- **Product backends** handle domain-specific logic (port 4010-4018)
|
||||
- **Web apps** use Next.js 16 + React 19
|
||||
- **Mobile apps** use native platforms (SwiftUI, Jetpack Compose, React Native)
|
||||
|
||||
|
||||
@ -199,7 +199,7 @@ export async function enterpriseRoutes(app: FastifyInstance) {
|
||||
id: `usr_${randomUUID()}`,
|
||||
productId: idp.productId,
|
||||
email,
|
||||
passwordHash: `sso_${randomUUID()}`, // SSO-only — no password login
|
||||
passwordHash: await userRepo.hashPassword(randomUUID()), // SSO-only — random bcrypt hash
|
||||
plan: 'free',
|
||||
role: 'user',
|
||||
displayName: samlData.attributes?.displayName ?? email.split('@')[0],
|
||||
@ -211,6 +211,8 @@ export async function enterpriseRoutes(app: FastifyInstance) {
|
||||
primaryProductId: idp.productId,
|
||||
memberships: [{ productId: idp.productId, plan: 'free', role: 'user', firstAccessAt: now }],
|
||||
});
|
||||
} else {
|
||||
await userRepo.updateLastLogin(user.id);
|
||||
}
|
||||
|
||||
// Issue tokens
|
||||
@ -306,7 +308,7 @@ export async function enterpriseRoutes(app: FastifyInstance) {
|
||||
id: `usr_${randomUUID()}`,
|
||||
productId: idp.productId,
|
||||
email,
|
||||
passwordHash: `sso_${randomUUID()}`,
|
||||
passwordHash: await userRepo.hashPassword(randomUUID()), // SSO-only — random bcrypt hash
|
||||
plan: 'free',
|
||||
role: 'user',
|
||||
displayName: displayName ?? email.split('@')[0],
|
||||
@ -318,6 +320,8 @@ export async function enterpriseRoutes(app: FastifyInstance) {
|
||||
primaryProductId: idp.productId,
|
||||
memberships: [{ productId: idp.productId, plan: 'free', role: 'user', firstAccessAt: now }],
|
||||
});
|
||||
} else {
|
||||
await userRepo.updateLastLogin(user.id);
|
||||
}
|
||||
|
||||
// Issue tokens
|
||||
|
||||
@ -123,7 +123,7 @@ export async function remove(id: string): Promise<boolean> {
|
||||
}
|
||||
|
||||
export async function hashPassword(password: string): Promise<string> {
|
||||
return bcrypt.hash(password, 10);
|
||||
return bcrypt.hash(password, 12);
|
||||
}
|
||||
|
||||
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user