fix: document service hangs in API-key auth contexts (#85)
* fix: use caller's supabase client in ensureDocumentsBucket The bucket check was creating its own cookie-dependent service client via createServiceClient(), which calls `await cookies()`. This hangs in API-key auth contexts (MCP server) where no cookie store exists. Now uses the caller's supabase client instead — both uploadDocument() and createNewVersion() already receive a service-role client. Removes the unused createServiceClient import. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use cookieless service client in ensureDocumentsBucket ensureDocumentsBucket() needs a service-role client for storage admin operations (getBucket/createBucket). Previously it used createServiceClient() which calls `await cookies()` — this hangs in API-key auth contexts (e.g. MCP server) where no cookie store exists. Now uses createServiceClientNoCookies() internally, which provides a service-role client without cookie dependency. This is correct for all callers: both web API routes (which pass user-level clients) and the MCP server (which passes a cookieless service client) — bucket admin always requires service-role regardless of the caller's auth context. Also cleans up stale test mock that referenced the removed import. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
7571b85d1a
commit
a088df436e
@@ -43,9 +43,8 @@ function makeClient(storageOverrides: Record<string, unknown> = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep createServiceClient mock since ensureDocumentsBucket still uses it
|
vi.mock('@/lib/auth/api-keys', () => ({
|
||||||
vi.mock('@/lib/supabase/server', () => ({
|
createServiceClientNoCookies: vi.fn(() => makeClient()),
|
||||||
createServiceClient: vi.fn(async () => makeClient()),
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
import { uploadDocument, createNewVersion, verifyIntegrity, _resetBucketVerified } from '../document-service'
|
import { uploadDocument, createNewVersion, verifyIntegrity, _resetBucketVerified } from '../document-service'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { SupabaseClient } from '@supabase/supabase-js'
|
import type { SupabaseClient } from '@supabase/supabase-js'
|
||||||
import { createServiceClient } from '@/lib/supabase/server'
|
import { createServiceClientNoCookies } from '@/lib/auth/api-keys'
|
||||||
import { eventBus } from '@/lib/events'
|
import { eventBus } from '@/lib/events'
|
||||||
import type { DocumentAttachment, DocumentUploadSource } from '@/types'
|
import type { DocumentAttachment, DocumentUploadSource } from '@/types'
|
||||||
|
|
||||||
@@ -21,15 +21,19 @@ export function _resetBucketVerified() {
|
|||||||
/**
|
/**
|
||||||
* Ensure the 'documents' storage bucket exists, creating it if missing.
|
* Ensure the 'documents' storage bucket exists, creating it if missing.
|
||||||
* Runs once per process lifetime (same pattern as ensureInitialized).
|
* Runs once per process lifetime (same pattern as ensureInitialized).
|
||||||
|
*
|
||||||
|
* Uses a cookieless service-role client for bucket admin operations
|
||||||
|
* (getBucket/createBucket require service-role). This avoids the cookie
|
||||||
|
* dependency that hangs in API-key auth contexts (e.g. MCP server).
|
||||||
*/
|
*/
|
||||||
async function ensureDocumentsBucket(): Promise<void> {
|
async function ensureDocumentsBucket(): Promise<void> {
|
||||||
if (bucketVerified) return
|
if (bucketVerified) return
|
||||||
|
|
||||||
const supabase = await createServiceClient()
|
const serviceClient = createServiceClientNoCookies()
|
||||||
const { data: bucket } = await supabase.storage.getBucket('documents')
|
const { data: bucket } = await serviceClient.storage.getBucket('documents')
|
||||||
|
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
await supabase.storage.createBucket('documents', {
|
await serviceClient.storage.createBucket('documents', {
|
||||||
public: false,
|
public: false,
|
||||||
fileSizeLimit: 52428800, // 50 MB
|
fileSizeLimit: 52428800, // 50 MB
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user