Phases 28-31 archived to milestones/v2.2-phases/ Requirements and roadmap snapshots archived to milestones/ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | user_setup | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 28-profile-and-logto-integration | 03 | execute | 2 |
|
|
false |
|
|
Purpose: Make the profile page discoverable via navigation, provide the createdAt data needed by the profile page, and ensure Logto is configured with GearBox branding and security policies so users never feel they've left the app (D-07). Output: Updated navigation, extended /me endpoint, Logto configuration checkpoints
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/28-profile-and-logto-integration/28-CONTEXT.md @.planning/phases/28-profile-and-logto-integration/28-RESEARCH.md@src/client/routes/__root.tsx @src/server/routes/auth.ts @src/client/hooks/useAuth.ts
<threat_model>
Threat Model
| ID | Threat | Severity | Mitigation |
|---|---|---|---|
| T-28-10 | createdAt leaks information about user registration patterns | LOW | Only return for authenticated user's own data (already behind /me auth) |
| </threat_model> |
In the GET /me handler, after getOrCreateUser(db, auth.sub), also query the full user record to get createdAt:
app.get("/me", async (c) => {
const auth = await getAuth(c);
if (auth) {
const db = c.get("db");
const user = await getOrCreateUser(db, auth.sub);
// Get full user record for createdAt
const [fullUser] = await db.select().from(users).where(eq(users.id, user.id));
return c.json({
user: {
id: user.id,
email: auth.email,
createdAt: fullUser?.createdAt?.toISOString() ?? null,
},
authenticated: true,
});
}
return c.json({ user: null, authenticated: false });
});
Add necessary imports: import { eq } from "drizzle-orm" and import { users } from "../../db/schema.ts".
Update src/client/hooks/useAuth.ts — extend AuthState interface:
Add createdAt to the user type:
interface AuthState {
user: { id: string; email?: string; createdAt?: string } | null;
authenticated: boolean;
}
Update src/client/routes/__root.tsx — add profile link:
Find the navigation section where settings/logout links exist (look for /settings or useLogout). Add a "Profile" link next to or near the settings link:
<Link to="/profile" className="...">Profile</Link>
Use the same styling as the existing settings link. If the nav uses icons, use the "User" or "CircleUser" icon from the curated Lucide icon set (check lib/iconData for available icons). If no icon-based nav, use text link.
Only show the Profile link when auth?.authenticated is true (same guard as existing settings/logout links).
<acceptance_criteria>
- src/server/routes/auth.ts /me endpoint response includes createdAt field
- src/server/routes/auth.ts imports users from schema and eq from drizzle-orm
- src/client/hooks/useAuth.ts AuthState interface includes createdAt?: string
- src/client/routes/__root.tsx contains a Link to /profile
- The profile link is only visible when authenticated
</acceptance_criteria>
grep -q "createdAt" src/server/routes/auth.ts && grep -q "createdAt" src/client/hooks/useAuth.ts && grep -q "/profile" src/client/routes/__root.tsx
/me returns createdAt, AuthState type includes it, navigation has profile link visible to authenticated users
D-07: Sign-in page branding — In Logto Console > Sign-in & account > Branding:
- Upload GearBox logo (PNG/SVG, dark version for white background)
- Set brand color to
#374151(gray-700) - Add custom CSS to match GearBox styling. Key selectors:
div[class$=container]— setfont-familyto match system font stackbutton[class$=primary]— setbackground-color: #374151,border-radius: 0.5reminput[class$=input]— setborder-color: #e5e7eb(gray-200),border-radius: 0.5rem
- Verify by visiting /login — page should feel like GearBox, not generic Logto
D-08: Custom domain (optional, if DNS supports it):
- Configure reverse proxy to serve Logto under
auth.gearbox.de - Update
OIDC_ISSUERenv var tohttps://auth.gearbox.de/oidc - Update
OIDC_REDIRECT_URIto use the custom domain
D-09: Social connectors — In Logto Console > Connectors > Social:
- Google: Create OAuth 2.0 credentials in Google Cloud Console. Configure Google connector in Logto with client ID and secret.
- GitHub: Create OAuth App in GitHub Developer Settings. Configure GitHub connector in Logto with client ID and secret.
- Enable both in Sign-in & account > Sign-up & sign-in > Social sign-in section.
D-10: Email verification — In Logto Console > Sign-in & account > Sign-up & sign-in:
- Set email verification to "Required" for new signups
D-11: Password policy — In Logto Console > Sign-in & account > Password policy:
- Minimum length: 8
- Require: uppercase letter
- Require: lowercase letter
- Require: number
<acceptance_criteria>
- Visiting /login shows GearBox-branded login page (logo, colors)
- Google and GitHub social sign-in buttons appear on the login page
- Creating a new account requires email verification
- Attempting to set a password shorter than 8 chars or without mixed case is rejected </acceptance_criteria> echo "Manual verification required — Logto Console configuration" Logto sign-in page shows GearBox branding with logo and matching colors, Google and GitHub social sign-in are available, email verification is required, password policy enforces 8+ chars with mixed case and number
<success_criteria>
- Profile page is discoverable via navigation
- /me endpoint provides createdAt for member-since display
- Logto sign-in page is branded to match GearBox (D-07)
- Google and GitHub social connectors are configured (D-09)
- Email verification required at signup (D-10)
- Password policy enforces strength requirements (D-11) </success_criteria>