A third party ATProto appview

CORS was too strict

Changed files
+9 -5
server
+4
server/index.ts
··· 132 132 req.method === 'OPTIONS' 133 133 ) { 134 134 res.setHeader('Access-Control-Allow-Origin', '*'); 135 + } else if (req.path.startsWith('/xrpc/')) { 136 + // XRPC endpoints use Authorization header auth, not cookies, so CSRF isn't a concern 137 + // Allow cross-origin requests for ATProto clients 138 + res.setHeader('Access-Control-Allow-Origin', '*'); 135 139 } else { 136 140 // For state-changing operations without origin, reject to prevent CSRF 137 141 return res.status(403).json({
+5 -5
server/storage.ts
··· 3114 3114 conditions.push(sql`${notifications.indexedAt} <= ${seenAt}`); 3115 3115 } 3116 3116 3117 - return await db 3117 + return await this.db 3118 3118 .select() 3119 3119 .from(notifications) 3120 3120 .where(and(...conditions)) ··· 3123 3123 } 3124 3124 3125 3125 async getUnreadNotificationCount(recipientDid: string): Promise<number> { 3126 - const result = await db 3126 + const result = await this.db 3127 3127 .select({ count: sql<number>`count(*)` }) 3128 3128 .from(notifications) 3129 3129 .where( ··· 3155 3155 } 3156 3156 3157 3157 async createList(list: InsertList): Promise<List> { 3158 - const [newList] = await db.insert(lists).values(list).returning(); 3158 + const [newList] = await this.db.insert(lists).values(list).returning(); 3159 3159 return newList; 3160 3160 } 3161 3161 ··· 3709 3709 3710 3710 // Video job operations 3711 3711 async createVideoJob(job: InsertVideoJob): Promise<VideoJob> { 3712 - const [videoJob] = await db.insert(videoJobs).values(job).returning(); 3712 + const [videoJob] = await this.db.insert(videoJobs).values(job).returning(); 3713 3713 return videoJob; 3714 3714 } 3715 3715 3716 3716 async getVideoJob(jobId: string): Promise<VideoJob | undefined> { 3717 - const [job] = await db 3717 + const [job] = await this.db 3718 3718 .select() 3719 3719 .from(videoJobs) 3720 3720 .where(eq(videoJobs.jobId, jobId))