-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path20241228_vertex_ai_oauth_setup.sql
More file actions
366 lines (300 loc) · 13.7 KB
/
20241228_vertex_ai_oauth_setup.sql
File metadata and controls
366 lines (300 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
-- ============================================
-- VERTEX AI & GOOGLE CLOUD OAUTH SETUP
-- ============================================
-- Migration: Add support for Google Cloud OAuth connections and Vertex AI integration
-- Created: 2024-12-28
-- Purpose: Enable Vertex AI chat with Google Cloud OAuth authentication
-- ============================================
-- 1. OAUTH CONNECTIONS TABLE
-- ============================================
-- Store OAuth refresh tokens and connection metadata for external services
CREATE TABLE IF NOT EXISTS public.oauth_connections (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Provider identification
provider TEXT NOT NULL CHECK (provider IN ('google_cloud', 'github', 'microsoft', 'aws', 'other')),
provider_user_id TEXT, -- External user ID from the provider (e.g., Google user ID)
provider_email TEXT, -- Email associated with the OAuth account
-- OAuth tokens
access_token TEXT, -- Current access token (short-lived, optional storage)
refresh_token TEXT NOT NULL, -- Long-lived refresh token (encrypted in production)
token_type TEXT DEFAULT 'Bearer',
expires_at TIMESTAMPTZ, -- When the access token expires
-- Scopes and permissions
scopes TEXT[], -- Array of granted OAuth scopes
-- Connection status
is_active BOOLEAN DEFAULT TRUE,
connected_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_refreshed_at TIMESTAMPTZ DEFAULT NOW(),
last_used_at TIMESTAMPTZ DEFAULT NOW(),
-- Metadata
metadata JSONB DEFAULT '{}', -- Additional provider-specific data
error_count INTEGER DEFAULT 0, -- Track consecutive refresh failures
last_error TEXT, -- Last error message if refresh failed
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for oauth_connections
CREATE INDEX IF NOT EXISTS idx_oauth_connections_provider_active
ON public.oauth_connections(provider, is_active)
WHERE is_active = TRUE;
CREATE INDEX IF NOT EXISTS idx_oauth_connections_provider_email
ON public.oauth_connections(provider, provider_email);
CREATE INDEX IF NOT EXISTS idx_oauth_connections_last_used
ON public.oauth_connections(last_used_at DESC)
WHERE is_active = TRUE;
-- Comments
COMMENT ON TABLE public.oauth_connections IS 'Stores OAuth connection credentials for external services like Google Cloud, GitHub, etc.';
COMMENT ON COLUMN public.oauth_connections.refresh_token IS 'Long-lived refresh token - ENCRYPT IN PRODUCTION using Supabase Vault or similar';
COMMENT ON COLUMN public.oauth_connections.scopes IS 'OAuth scopes granted to this connection (e.g., gmail.send, drive.file)';
COMMENT ON COLUMN public.oauth_connections.error_count IS 'Consecutive refresh failures - auto-disable connection after threshold';
-- ============================================
-- 2. AI PROVIDER USAGE TRACKING
-- ============================================
-- Track which AI provider (Vertex AI, Gemini, DeepSeek) handled each request
CREATE TABLE IF NOT EXISTS public.ai_provider_usage_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Request identification
request_id TEXT, -- Unique identifier for the chat request
session_key TEXT, -- Conversation session identifier
-- Provider information
provider TEXT NOT NULL, -- 'vertex-ai', 'gemini-api', 'deepseek', 'emergency-static'
model TEXT, -- Model used (e.g., 'gemini-1.5-pro', 'deepseek-chat')
executive_function TEXT, -- Which edge function was called (e.g., 'ai-chat', 'coo-chat')
-- Request details
message_count INTEGER, -- Number of messages in the request
has_images BOOLEAN DEFAULT FALSE, -- Whether images were included
has_tool_calls BOOLEAN DEFAULT FALSE, -- Whether tool calls were executed
tool_calls_count INTEGER DEFAULT 0, -- Number of tools invoked
-- Performance metrics
execution_time_ms INTEGER, -- Time taken to process request
token_count_input INTEGER, -- Approximate input tokens
token_count_output INTEGER, -- Approximate output tokens
-- OAuth authentication
oauth_authenticated BOOLEAN DEFAULT FALSE, -- Whether OAuth was used
oauth_connection_id UUID REFERENCES public.oauth_connections(id), -- Link to OAuth connection used
-- Success tracking
success BOOLEAN NOT NULL,
fallback_level INTEGER DEFAULT 0, -- 0=primary, 1=first fallback, 2=second fallback, etc.
error_message TEXT, -- Error if failed
-- Timestamps
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for ai_provider_usage_log
CREATE INDEX IF NOT EXISTS idx_ai_provider_usage_provider
ON public.ai_provider_usage_log(provider, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_ai_provider_usage_session
ON public.ai_provider_usage_log(session_key, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_ai_provider_usage_success
ON public.ai_provider_usage_log(success, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_ai_provider_usage_oauth
ON public.ai_provider_usage_log(oauth_authenticated, timestamp DESC)
WHERE oauth_authenticated = TRUE;
CREATE INDEX IF NOT EXISTS idx_ai_provider_usage_timestamp
ON public.ai_provider_usage_log(timestamp DESC);
-- Comments
COMMENT ON TABLE public.ai_provider_usage_log IS 'Tracks AI provider usage for analytics, billing, and performance monitoring';
COMMENT ON COLUMN public.ai_provider_usage_log.fallback_level IS '0=primary provider, 1=first fallback, 2=second fallback, etc.';
COMMENT ON COLUMN public.ai_provider_usage_log.oauth_authenticated IS 'TRUE if request used Google Cloud OAuth (Vertex AI)';
-- ============================================
-- 3. GOOGLE CLOUD SERVICE USAGE LOG
-- ============================================
-- Track usage of Google Cloud services (Gmail, Drive, Sheets, Calendar)
CREATE TABLE IF NOT EXISTS public.google_cloud_service_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Service identification
service TEXT NOT NULL CHECK (service IN ('gmail', 'drive', 'sheets', 'calendar', 'vertex_ai', 'other')),
operation TEXT NOT NULL, -- 'send_email', 'list_files', 'create_spreadsheet', 'create_event', etc.
-- Request details
oauth_connection_id UUID REFERENCES public.oauth_connections(id),
request_parameters JSONB DEFAULT '{}', -- Operation-specific parameters
-- Response details
success BOOLEAN NOT NULL,
response_data JSONB DEFAULT '{}', -- Operation result (sanitized, no sensitive data)
error_message TEXT,
-- Performance
execution_time_ms INTEGER,
-- Associated with AI chat request
ai_request_id UUID REFERENCES public.ai_provider_usage_log(id),
-- Timestamps
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for google_cloud_service_log
CREATE INDEX IF NOT EXISTS idx_google_service_log_service
ON public.google_cloud_service_log(service, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_google_service_log_oauth_connection
ON public.google_cloud_service_log(oauth_connection_id, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_google_service_log_success
ON public.google_cloud_service_log(success, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_google_service_log_timestamp
ON public.google_cloud_service_log(timestamp DESC);
-- Comments
COMMENT ON TABLE public.google_cloud_service_log IS 'Tracks Google Cloud service operations for billing and monitoring';
COMMENT ON COLUMN public.google_cloud_service_log.response_data IS 'Sanitized response data - DO NOT store sensitive information';
-- ============================================
-- 4. VIEWS FOR MONITORING
-- ============================================
-- View: OAuth Connection Health
CREATE OR REPLACE VIEW public.oauth_connection_health AS
SELECT
provider,
COUNT(*) as total_connections,
COUNT(*) FILTER (WHERE is_active = TRUE) as active_connections,
COUNT(*) FILTER (WHERE error_count > 0) as connections_with_errors,
MAX(last_used_at) as most_recent_use,
MAX(last_refreshed_at) as most_recent_refresh,
AVG(error_count) as avg_error_count
FROM public.oauth_connections
GROUP BY provider;
COMMENT ON VIEW public.oauth_connection_health IS 'Summary of OAuth connection status by provider';
-- View: AI Provider Performance
CREATE OR REPLACE VIEW public.ai_provider_performance AS
SELECT
provider,
DATE_TRUNC('hour', timestamp) as hour,
COUNT(*) as request_count,
COUNT(*) FILTER (WHERE success = TRUE) as successful_requests,
AVG(execution_time_ms) as avg_execution_time_ms,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY execution_time_ms) as p95_execution_time_ms,
AVG(fallback_level) as avg_fallback_level,
COUNT(*) FILTER (WHERE oauth_authenticated = TRUE) as oauth_requests
FROM public.ai_provider_usage_log
WHERE timestamp > NOW() - INTERVAL '24 hours'
GROUP BY provider, DATE_TRUNC('hour', timestamp)
ORDER BY hour DESC, request_count DESC;
COMMENT ON VIEW public.ai_provider_performance IS '24-hour AI provider performance metrics with OAuth tracking';
-- View: Google Cloud Service Usage Summary
CREATE OR REPLACE VIEW public.google_cloud_service_summary AS
SELECT
service,
operation,
DATE_TRUNC('day', timestamp) as day,
COUNT(*) as operation_count,
COUNT(*) FILTER (WHERE success = TRUE) as successful_operations,
AVG(execution_time_ms) as avg_execution_time_ms
FROM public.google_cloud_service_log
WHERE timestamp > NOW() - INTERVAL '7 days'
GROUP BY service, operation, DATE_TRUNC('day', timestamp)
ORDER BY day DESC, operation_count DESC;
COMMENT ON VIEW public.google_cloud_service_summary IS '7-day Google Cloud service usage summary';
-- ============================================
-- 5. FUNCTIONS FOR AUTOMATION
-- ============================================
-- Function: Update last_used_at on OAuth connections
CREATE OR REPLACE FUNCTION public.update_oauth_connection_last_used()
RETURNS TRIGGER AS $$
BEGIN
UPDATE public.oauth_connections
SET last_used_at = NOW()
WHERE id = NEW.oauth_connection_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger: Auto-update OAuth connection last_used_at
DROP TRIGGER IF EXISTS trigger_update_oauth_last_used ON public.ai_provider_usage_log;
CREATE TRIGGER trigger_update_oauth_last_used
AFTER INSERT ON public.ai_provider_usage_log
FOR EACH ROW
WHEN (NEW.oauth_connection_id IS NOT NULL)
EXECUTE FUNCTION public.update_oauth_connection_last_used();
-- Function: Auto-disable OAuth connections with too many errors
CREATE OR REPLACE FUNCTION public.check_oauth_connection_errors()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.error_count >= 5 THEN
NEW.is_active = FALSE;
RAISE NOTICE 'OAuth connection % disabled due to % consecutive errors', NEW.id, NEW.error_count;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger: Auto-disable failing OAuth connections
DROP TRIGGER IF EXISTS trigger_check_oauth_errors ON public.oauth_connections;
CREATE TRIGGER trigger_check_oauth_errors
BEFORE UPDATE ON public.oauth_connections
FOR EACH ROW
WHEN (NEW.error_count <> OLD.error_count)
EXECUTE FUNCTION public.check_oauth_connection_errors();
-- ============================================
-- 6. UTILITY QUERIES (for monitoring)
-- ============================================
-- These are example queries - not executed during migration
/*
-- Check OAuth connection status
SELECT * FROM public.oauth_connection_health;
-- Get most recent Vertex AI requests
SELECT
provider,
model,
oauth_authenticated,
execution_time_ms,
success,
timestamp
FROM public.ai_provider_usage_log
WHERE provider = 'vertex-ai'
ORDER BY timestamp DESC
LIMIT 10;
-- Count AI provider usage by provider (last 24 hours)
SELECT
provider,
COUNT(*) as request_count,
COUNT(*) FILTER (WHERE success = TRUE) as successful,
AVG(execution_time_ms) as avg_time_ms,
COUNT(*) FILTER (WHERE oauth_authenticated = TRUE) as oauth_requests
FROM public.ai_provider_usage_log
WHERE timestamp > NOW() - INTERVAL '24 hours'
GROUP BY provider
ORDER BY request_count DESC;
-- Check Google Cloud service usage
SELECT * FROM public.google_cloud_service_summary
ORDER BY day DESC, operation_count DESC
LIMIT 20;
-- Find OAuth connections that need refresh
SELECT
provider,
provider_email,
last_refreshed_at,
error_count,
last_error
FROM public.oauth_connections
WHERE is_active = TRUE
AND (last_refreshed_at < NOW() - INTERVAL '1 hour' OR error_count > 0)
ORDER BY last_refreshed_at ASC;
*/
-- ============================================
-- 7. ROW LEVEL SECURITY (RLS)
-- ============================================
-- Enable RLS for security (adjust policies based on your auth model)
ALTER TABLE public.oauth_connections ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ai_provider_usage_log ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.google_cloud_service_log ENABLE ROW LEVEL SECURITY;
-- Policy: Service role can access everything
CREATE POLICY "Service role has full access to oauth_connections"
ON public.oauth_connections
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
CREATE POLICY "Service role has full access to ai_provider_usage_log"
ON public.ai_provider_usage_log
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
CREATE POLICY "Service role has full access to google_cloud_service_log"
ON public.google_cloud_service_log
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- ============================================
-- MIGRATION COMPLETE
-- ============================================
-- Verify tables were created
SELECT
tablename,
schemaname
FROM pg_tables
WHERE schemaname = 'public'
AND tablename IN ('oauth_connections', 'ai_provider_usage_log', 'google_cloud_service_log')
ORDER BY tablename;