File size: 2,807 Bytes
2a26b7d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
-- ============================================================
--  SafeAIScan β€” Phase 1 Enterprise Upgrade Migration
--  Run once in Supabase SQL Editor. All statements are
--  idempotent (IF NOT EXISTS) β€” safe to re-run.
-- ============================================================

-- ── 1. Audit log table (item 10: Enterprise Readiness) ─────
-- Stores: scan events, login events, subscription events, admin actions
CREATE TABLE IF NOT EXISTS audit_logs (
  id          UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id     UUID        REFERENCES users(id) ON DELETE SET NULL,
  org_id      UUID,
  action      TEXT        NOT NULL,    -- e.g. "scan", "login", "register",
                                        -- "key_rotate", "subscription_cancel",
                                        -- "enterprise_inquiry", "pdf_export"
  resource    TEXT,                    -- e.g. "/api/analyze"
  ip_address  TEXT,
  metadata    JSONB,
  created_at  TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_audit_logs_org_created
  ON audit_logs(org_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_audit_logs_user_created
  ON audit_logs(user_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_audit_logs_action
  ON audit_logs(action);

-- RLS: users can see their own audit rows; service role bypasses for org queries
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS audit_logs_own_rows ON audit_logs;
CREATE POLICY audit_logs_own_rows ON audit_logs
  FOR SELECT USING (auth.uid()::text = user_id::text);


-- ── 2. scans table: security_score trend support ───────────
-- result_json already exists and is JSONB β€” security_score is stored
-- inside it (no new column needed). Add created_at index for trend queries.
CREATE INDEX IF NOT EXISTS idx_scans_user_created
  ON scans(user_id, created_at DESC);


-- ── 3. scan_tasks: ensure result_json can hold repo_health /
--      dependency_findings (already JSONB β€” no schema change needed,
--      this is a no-op safety check) ──────────────────────────
DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.columns
    WHERE table_name = 'scan_tasks' AND column_name = 'result_json'
  ) THEN
    ALTER TABLE scan_tasks ADD COLUMN result_json JSONB;
  END IF;
END $$;


-- ── 4. Verification ──────────────────────────────────────────
SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_name IN ('audit_logs', 'scans', 'scan_tasks')
  AND column_name IN ('id','user_id','org_id','action','metadata','result_json','created_at')
ORDER BY table_name, column_name;