mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
**Changes** - Extracted tracing conditional to an `isTracingAllowed` helper with unit tests (the function is simple but sensitive hence the extra testing precaution) - Disables Braintrust tracing for projects in EU database regions (region prefix `eu-`) to address GDPR data residency concerns - Disables Braintrust tracing for orgs whose owners have signed the previous DPA, as a stopgap during the 30-day notice period for the updated DPA that adds Braintrust as a subprocessor - Refactored `org-ai-details.ts` → `ai-details.ts`, splitting `getOrgAIDetails` into separate org and project helpers to cleanly scope the EU-region check at the project level DPA check uses the newly added `/documents/dpa-signed` endpoint from https://github.com/supabase/platform/pull/31060. This PR includes regenerated `api.d.ts` and `platform.d.ts` from running `pnpm codegen` in `packages/api-types` to get type safety on this new endpoint. Note tracing is still yet to be activated in production, this is a preparatory step. **To verify** Send a chat message and check for the `x-braintrust-span-id` response header on `POST /api/ai/sql/generate-v4` — it should be absent for DPA-signed orgs or EU-region projects, and present otherwise. <img width="3594" height="1992" alt="CleanShot 2026-04-03 at 14 28 58@2x" src="https://github.com/user-attachments/assets/4c91d7ad-2604-4531-a78e-dedf41632fa5" /> If you have access to the Braintrust dashboard, you can also verify whether logs are produced or not in the Assistant project there. Closes AI-570 Closes AI-569 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Tracks organization DPA signing and detects EU-region projects * Assistant tracing now follows a combined compliance policy (HIPAA addon, DPA, project sensitivity, region) * Added helpers to fetch org and project AI details * **Documentation** * Expanded API docs with additional examples and clarified parameter descriptions * Added response schemas for subscription preview and document status * **Tests** * Added/updated tests covering DPA/region behavior and tracing policy enforcement <!-- end of auto-generated comment: release notes by coderabbit.ai -->
89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
import { UIMessage } from 'ai'
|
|
import { sanitizeMessagePart } from 'lib/ai/tools/tool-sanitizer'
|
|
import { expect, test, vi } from 'vitest'
|
|
|
|
// End of third-party imports
|
|
|
|
import generateV4 from '../../pages/api/ai/sql/generate-v4'
|
|
|
|
vi.mock('lib/ai/tools/tool-sanitizer', () => ({
|
|
sanitizeMessagePart: vi.fn((part) => part),
|
|
}))
|
|
|
|
test('generateV4 calls the tool sanitizer', async () => {
|
|
const mockReq = {
|
|
method: 'POST',
|
|
headers: {
|
|
authorization: 'Bearer test-token',
|
|
},
|
|
body: {
|
|
messages: [
|
|
{
|
|
id: 'test-msg-id',
|
|
role: 'assistant',
|
|
parts: [
|
|
{
|
|
type: 'tool-execute_sql',
|
|
state: 'output-available',
|
|
toolCallId: 'test-tool-call-id',
|
|
input: { sql: 'SELECT * FROM users' },
|
|
output: [{ id: 1, name: 'test-output' }],
|
|
},
|
|
],
|
|
},
|
|
] satisfies UIMessage[],
|
|
projectRef: 'test-project',
|
|
connectionString: 'test-connection',
|
|
orgSlug: 'test-org',
|
|
},
|
|
on: vi.fn(),
|
|
}
|
|
|
|
const mockRes = {
|
|
status: vi.fn(() => mockRes),
|
|
json: vi.fn(() => mockRes),
|
|
setHeader: vi.fn(() => mockRes),
|
|
}
|
|
|
|
vi.mock('lib/ai/ai-details', () => ({
|
|
getOrgAIDetails: vi.fn().mockResolvedValue({
|
|
aiOptInLevel: 'schema_and_log_and_data',
|
|
hasAccessToAdvanceModel: true,
|
|
isDpaSigned: false,
|
|
}),
|
|
getProjectAIDetails: vi.fn().mockResolvedValue({
|
|
region: 'us-east-1',
|
|
isSensitive: false,
|
|
}),
|
|
}))
|
|
|
|
vi.mock('lib/ai/model', () => ({
|
|
getModel: vi.fn().mockResolvedValue({
|
|
modelParams: { model: {} },
|
|
promptProviderOptions: {},
|
|
}),
|
|
}))
|
|
|
|
vi.mock('data/sql/execute-sql-query', () => ({
|
|
executeSql: vi.fn().mockResolvedValue({ result: [] }),
|
|
}))
|
|
|
|
vi.mock('lib/ai/tools', () => ({
|
|
getTools: vi.fn().mockResolvedValue({}),
|
|
}))
|
|
|
|
vi.mock('ai', async () => {
|
|
const actual = await vi.importActual('ai')
|
|
return {
|
|
...actual,
|
|
streamText: vi.fn().mockReturnValue({
|
|
pipeUIMessageStreamToResponse: vi.fn(),
|
|
}),
|
|
}
|
|
})
|
|
|
|
await generateV4(mockReq as any, mockRes as any)
|
|
|
|
expect(sanitizeMessagePart).toHaveBeenCalled()
|
|
})
|