-
Notifications
You must be signed in to change notification settings - Fork 0
Copilot test #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Copilot test #6
Changes from all commits
e1ab1d2
fffeea3
7b54fd5
9f26122
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Bugbot Rules | ||
|
|
||
| This file contains rules and preferences for Cursor Bugbot to customize its analysis and avoid false positive bug reports. | ||
|
|
||
| ## Authentication Flow Rules | ||
|
|
||
| ### Challenge/Verification Code Retry Behavior | ||
|
|
||
| **DO NOT** flag as a bug if verification challenges are cleared before user creation completes. | ||
|
|
||
| **Rationale**: In this codebase, we intentionally clear verification challenges immediately upon verification, before attempting user creation. If user creation fails (e.g., due to database errors), users will need to request a new verification challenge and post a new code. This is an acceptable UX trade-off for this application. | ||
|
|
||
| **Acceptable pattern**: | ||
| ```typescript | ||
| // Clear challenge before user creation | ||
| await clearChallenge(handle); | ||
|
|
||
| // Then attempt user creation | ||
| const user = await getOrCreateUser(handle); | ||
| if (!user) { | ||
| return error(500, 'Failed to create user'); | ||
| } | ||
| ``` | ||
|
|
||
| This pattern should NOT be flagged as requiring the challenge to be cleared only after successful user creation. | ||
|
|
||
| ## File Exclusions | ||
|
|
||
| ### Database Migration Files | ||
|
|
||
| **DO NOT** analyze or report bugs in database migration files. | ||
|
|
||
| **Paths to exclude**: | ||
| - `supabase/migrations/**/*.sql` | ||
| - Any file matching the pattern `**/migrations/**/*.sql` | ||
|
|
||
| **Rationale**: Database migration files are intentionally written in a specific format and are version-controlled as historical records. They should not be modified after being applied to production databases. Any issues with migrations should be addressed through new migration files, not by flagging the existing ones. | ||
|
|
||
| ## Code Style Enforcement | ||
|
|
||
| ### JavaScript Style Guide Compliance | ||
|
|
||
| **DO** check for code style compliance with standard JavaScript style guidelines for `.js` files in the `src/` folder. | ||
|
|
||
| **Scope**: | ||
| - All `.js` files within `src/**/*.js` | ||
|
|
||
| **Style guidelines to enforce**: | ||
| - Consistent indentation (2 or 4 spaces, not tabs) | ||
| - Semicolon usage (either always or never, consistently) | ||
| - Quote style (single or double quotes, used consistently) | ||
| - Proper function declaration formatting | ||
| - Consistent spacing around operators and keywords | ||
| - Proper use of ES6+ features where appropriate | ||
| - Consistent naming conventions (camelCase for variables/functions, PascalCase for classes) | ||
|
|
||
| **Rationale**: Maintaining consistent code style in JavaScript files improves readability, reduces cognitive load during code reviews, and helps prevent subtle bugs. The `src/` folder contains the core application logic and should adhere to professional coding standards. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import type { Cookies } from '@sveltejs/kit'; | ||
| import { getUserByHandle } from '$lib/services/userService'; | ||
|
|
||
| export type SessionData = { | ||
| userId: string; | ||
| handle: string; | ||
| verifiedAt: string; | ||
| }; | ||
|
|
||
| /** | ||
| * Get the current session from cookies. | ||
| * Returns null if no valid session exists. | ||
| */ | ||
| export function getSession(cookies: Cookies): SessionData | null { | ||
| try { | ||
| const sessionCookie = cookies.get('session'); | ||
| if (!sessionCookie) return null; | ||
| const session = JSON.parse(sessionCookie) as SessionData; | ||
| // Basic validation | ||
| if (!session.userId || !session.handle || !session.verifiedAt) return null; | ||
| return session; | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Clear the session cookie. | ||
| */ | ||
| export function clearSession(cookies: Cookies): void { | ||
| cookies.delete('session', { path: '/' }); | ||
| } | ||
|
|
||
| /** | ||
| * Get the current authenticated user's handle. | ||
| * Returns null if not authenticated. | ||
| */ | ||
| export function getCurrentUserHandle(cookies: Cookies): string | null { | ||
| const session = getSession(cookies); | ||
| return session?.handle ?? null; | ||
| } | ||
|
|
||
|
Comment on lines
+1
to
+42
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,140 @@ | ||||||||||||
| import { getSupabaseAdmin } from '$lib/supabaseAdmin'; | ||||||||||||
| import { BskyAgent } from '@atproto/api'; | ||||||||||||
| import { BSKY_APPVIEW_BASE } from '$lib/config/bsky'; | ||||||||||||
|
|
||||||||||||
| export type User = { | ||||||||||||
| id: string; | ||||||||||||
| bskyHandle: string; | ||||||||||||
| bskyDid?: string | null; | ||||||||||||
| displayName?: string | null; | ||||||||||||
| avatarUrl?: string | null; | ||||||||||||
| verifiedAt: string; | ||||||||||||
| lastSeenAt: string; | ||||||||||||
| createdAt: string; | ||||||||||||
| updatedAt: string; | ||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| let agentPromise: Promise<BskyAgent> | null = null; | ||||||||||||
|
|
||||||||||||
| function getServiceBase(): string { | ||||||||||||
| return BSKY_APPVIEW_BASE.endsWith('/xrpc') | ||||||||||||
| ? BSKY_APPVIEW_BASE.slice(0, -('/xrpc'.length)) | ||||||||||||
| : BSKY_APPVIEW_BASE; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| async function getAgent(): Promise<BskyAgent> { | ||||||||||||
| if (!agentPromise) { | ||||||||||||
| agentPromise = (async () => { | ||||||||||||
| const agent = new BskyAgent({ service: getServiceBase() }); | ||||||||||||
| return agent; | ||||||||||||
| })(); | ||||||||||||
|
||||||||||||
| })(); | |
| })().catch((err) => { | |
| agentPromise = null; | |
| throw err; | |
| }); |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The profile is fetched twice in getOrCreateUser: once via resolveDidFromHandle (line 60) and again for display name and avatar (lines 66-69). This makes two API calls for the same data. Consider combining these into a single call by having resolveDidFromHandle return the full profile object, or create a new function that fetches both DID and profile data together. This reduces API calls and improves performance.
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new userService.ts module lacks test coverage. Other services in the same directory (accountOverrides.ts, accountsRegistry.ts, bskyService.ts, twitterService.ts) all have corresponding test files. The getOrCreateUser and getUserByHandle functions contain complex logic including external API calls, database operations, and error handling that should be tested. Consider adding userService.test.ts with test cases for successful user creation, DID resolution, profile fetching, database upsert errors, and null Supabase client scenarios.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,10 +7,30 @@ export const POST: RequestHandler = async ({ request }) => { | |
| const handle = (body?.handle ?? '').toString().trim(); | ||
|
|
||
| if (!handle) { | ||
| return new Response(JSON.stringify({ error: 'missing_handle' }), { | ||
| status: 400, | ||
| headers: { 'Content-Type': 'application/json' } | ||
| }); | ||
| return new Response( | ||
| JSON.stringify({ | ||
| error: 'missing_handle', | ||
| message: 'Bluesky handle is required. Please provide your handle (e.g., "example.bsky.social").' | ||
| }), | ||
| { | ||
| status: 400, | ||
| headers: { 'Content-Type': 'application/json' } | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| // Basic handle validation | ||
| if (!handle.includes('.') && !handle.includes('@')) { | ||
| return new Response( | ||
| JSON.stringify({ | ||
| error: 'invalid_handle', | ||
| message: 'Invalid Bluesky handle format. Handles should be in the format "example.bsky.social" or "@example.bsky.social".' | ||
| }), | ||
| { | ||
| status: 400, | ||
| headers: { 'Content-Type': 'application/json' } | ||
| } | ||
| ); | ||
|
Comment on lines
+22
to
+33
|
||
| } | ||
|
|
||
| // If an existing challenge exists and hasn't expired, reuse it (avoid generating multiple codes quickly) | ||
|
|
@@ -29,9 +49,15 @@ export const POST: RequestHandler = async ({ request }) => { | |
| { status: 200, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' } } | ||
| ); | ||
| } catch (e: any) { | ||
| return new Response(JSON.stringify({ error: 'create_challenge_failed', message: e?.message ?? 'Unknown error' }), { | ||
| status: 500, | ||
| headers: { 'Content-Type': 'application/json' } | ||
| }); | ||
| return new Response( | ||
| JSON.stringify({ | ||
| error: 'create_challenge_failed', | ||
| message: e?.message ?? 'An unexpected error occurred while creating the verification challenge. Please try again.' | ||
| }), | ||
| { | ||
| status: 500, | ||
| headers: { 'Content-Type': 'application/json' } | ||
| } | ||
| ); | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import getUserByHandle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot - is this the only place where getuserbyhandle is used? Are tehre any other places in the code where that is used?