The proper architecture is:
1. Nodes are created with coords_3d = NONE
2. User manually triggers /api/calculate-graph
3. UMAP calculates 3D coordinates from embeddings
4. Coordinates are updated in batch
Changed coords_3d TYPE from array<number> to option<array<number>>
to allow NONE values. This fixes production error:
"Found NONE for field coords_3d but expected array<number>"
Schema has been deployed to production.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated GOOGLE_EMBEDDING_DIMENSIONS to 3072 to match gemini-embedding-001 output
- Updated database schema embedding index from 768 to 3072 dimensions
- Recreated production database index with correct dimensions
- Added @vercel/analytics package for production analytics
- Added Analytics component to root layout
This fixes the galaxy visualization issue caused by dimension mismatch between
the embedding model output (3072) and the database index (768).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace manual OAuth implementation with official @atproto/oauth-client-node library to properly support DPoP (Demonstrating Proof of Possession) authentication.
Changes:
- Added @atproto/oauth-client-node dependency
- Created OAuth state store (SurrealDB-backed) for CSRF protection
- Created OAuth session store (SurrealDB-backed) for token persistence
- Created OAuth client singleton with localhost exception for development
- Rewrote /api/auth/login to use client.authorize()
- Rewrote /api/auth/callback to use client.callback() with DPoP
- Updated lib/auth/session.ts with getAuthenticatedAgent() for ATproto API calls
- Updated db/schema.surql with oauth_state and oauth_session tables
- Added scripts/apply-schema.js for database schema management
- Created plans/oauth-dpop-implementation.md with detailed implementation plan
- Removed legacy lib/auth/atproto.ts and lib/auth/oauth-state.ts
- Updated .env to use localhost exception (removed BLUESKY_CLIENT_ID)
The OAuth client now handles:
- PKCE code generation and verification
- DPoP proof generation and signing
- Automatic token refresh
- Session persistence across server restarts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement the core write-through cache pattern for node creation.
This is the architectural foundation of the application.
Changes:
- Add @google/generative-ai dependency for embeddings
- Create lib/db.ts: SurrealDB connection helper with JWT auth
- Create lib/ai.ts: AI embedding generation using text-embedding-004
- Create app/api/nodes/route.ts: POST endpoint implementing write-through cache
Write-through cache flow:
1. Authenticate user via SurrealDB JWT
2. Publish node to ATproto PDS (source of truth)
3. Generate 768-dimensional embedding via Google AI
4. Cache node + embedding + links in SurrealDB
Updated schema to use 768-dimensional embeddings (text-embedding-004)
instead of 1536 dimensions.
Security:
- Row-level permissions enforced via SurrealDB JWT
- All secrets server-side only
- ATproto OAuth tokens from secure cookies
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>