feat: Steward auth integration — Phase 1 (parallel with Privy)#446
feat: Steward auth integration — Phase 1 (parallel with Privy)#446
Conversation
- Import StewardLogin and StewardProvider from @stwd/react - Feature-flagged via NEXT_PUBLIC_STEWARD_AUTH_ENABLED env var - Shows passkey + email magic link when enabled - Self-contained: StewardProvider wraps only the login widget - Existing Privy auth flow completely unchanged when flag is off - On success, redirects to dashboard (same as Privy flow) Co-authored-by: wakesync <shadow@shad0w.xyz>
Mirrors privy-sync.ts pattern for Steward JWT-based authentication. Flow: 1. Look up existing user by steward_user_id 2. Check pending invites by email 3. Link to existing account if email matches 4. Create new user + organization Key differences from privy-sync: - Uses steward_user_id column instead of privy_user_id - JWT contains email/userId/walletAddress directly (no third-party API) - No anonymous user upgrade path (Steward has no anonymous users) Co-authored-by: wakesync <shadow@shad0w.xyz>
Mirrors privy-client.ts pattern for Steward-issued JWTs: - steward-client.ts: JWT verify via jose + in-memory LRU + Redis cache - auth.ts: Bearer JWT chain now tries Privy -> Steward -> API key - cache/keys.ts: add session.steward cache key + TTL (5min, same as Privy) Steward JIT sync is stubbed (TODO) pending steward-sync worker. invalidateSessionCaches now clears both Privy + Steward caches. Co-authored-by: wakesync <shadow@shad0w.xyz>
- Create packages/lib/providers/StewardProvider.tsx mirroring PrivyProvider pattern - StewardProvider wraps @stwd/react StewardProvider with auth config - AuthTokenSync dispatches 'steward-token-sync' events for non-React consumers - Graceful fallback: renders children without provider if URL unconfigured - Conditional activation via NEXT_PUBLIC_STEWARD_AUTH_ENABLED env var - Both auth providers coexist, managing separate auth state - Add @stwd/react@0.6.4, @stwd/sdk@0.7.2, @simplewebauthn/browser deps Co-authored-by: wakesync <shadow@shad0w.xyz>
One-time script to create a steward tenant for waifu.fun. Run after steward service is up. Co-authored-by: wakesync <shadow@shad0w.xyz>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro 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 |
Code Review — feat: Steward auth integration (Phase 1)Overall the structure is solid — mirrors Privy cleanly, feature-flagged, non-breaking. A few issues to address before merging. 🔴 Critical1. JIT sync is commented out but
// TODO: Import syncUserFromSteward once steward-sync module is created
// import { syncUserFromSteward } from "./steward-sync";…and the JIT path is fully commented out. But 2. Account linking silently overwrites In if (existingByEmail && existingByEmail.steward_user_id !== stewardUserId) {
// Linking Steward account...
await usersService.update(existingByEmail.id, { steward_user_id: stewardUserId, ... });This allows anyone who registers in Steward with email 🟡 Medium3. Double
4. Null dereference in slug uniqueness retry loop // steward-sync.ts — inside the while(await organizationsService.getBySlug(orgSlug)) loop
orgSlug = email ? generateSlugFromEmail(email) : generateSlugFromWallet(walletAddress!);If the code reaches this point via the if (email) orgSlug = generateSlugFromEmail(email);
else if (walletAddress) orgSlug = generateSlugFromWallet(walletAddress);
else { orgSlug = `user-${stewardUserId.substring(0,8)}-${Date.now().toString(36)}`; }🟠 Minor5. Duplicate import from import { StewardLogin } from "@stwd/react";
import { StewardProvider } from "@stwd/react";Merge into one import statement. 6. discordService.logUserSignup({
...
privyUserId: userWithOrg.privy_user_id || "", // always "" for Steward usersThis will always be an empty string for Steward signups and may mislead whoever reads those logs. Consider either omitting the field or using a different key name for the Steward path. 7. Calling ✅ Looks good
|
Summary
Add Steward as an alternative auth provider alongside Privy. Feature-flagged, non-breaking. Existing Privy auth untouched.
Type
Changes
New files
packages/lib/providers/StewardProvider.tsx— React provider wrapping @stwd/react, auto-syncs JWT via CustomEventpackages/lib/auth/steward-client.ts— JWT verification with 3-layer cache (in-memory LRU → Redis → local verify), mirrors privy-client.tspackages/lib/steward-sync.ts— User sync from Steward JWT to eliza-cloud user+org, mirrors privy-sync.ts (645 lines)packages/scripts/provision-waifu-tenant.ts— One-time script to create waifu.fun steward tenantModified files
app/layout.tsx— MaybeStewardProvider wrapper (gated on NEXT_PUBLIC_STEWARD_AUTH_ENABLED)app/login/page.tsx— Steward login section (passkey + email) above Privy options, feature-flaggedpackages/lib/auth.ts— Bearer auth chain: Privy → Steward → API key fallbackpackages/lib/cache/keys.ts— Added steward session cache keys + TTLpackage.json— Added @stwd/react, @stwd/sdk, @simplewebauthn/browserHow it works
NEXT_PUBLIC_STEWARD_AUTH_ENABLED=trueto show Steward loginEnv vars needed
Breaking Changes
Co-authored-by: wakesync shadow@shad0w.xyz