Skip to content

Commit af5154a

Browse files
feat: GitHub App webhook handler + review-core semantic module
- Add fetch handler for GitHub App webhooks (PR opened/synchronize) - HMAC SHA-256 signature verification - Enqueue review jobs on PR events - Add review-core semantic module (symbol extraction, duplicate detection) - Add D1 migrations and wrangler config for review worker Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d110862 commit af5154a

13 files changed

Lines changed: 2906 additions & 0 deletions

File tree

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
-- Merged D1 (SQLite) schema for CodeVetter control plane
2+
-- Converted from PostgreSQL migrations 0001_init, 0002_agent_metadata, 0003_indexing_tables
3+
4+
CREATE TABLE IF NOT EXISTS users (
5+
id TEXT PRIMARY KEY,
6+
github_user_id TEXT NOT NULL UNIQUE,
7+
github_login TEXT NOT NULL,
8+
display_name TEXT,
9+
avatar_url TEXT,
10+
email TEXT,
11+
created_at TEXT NOT NULL,
12+
updated_at TEXT NOT NULL
13+
);
14+
15+
CREATE TABLE IF NOT EXISTS oauth_accounts (
16+
id TEXT PRIMARY KEY,
17+
user_id TEXT NOT NULL REFERENCES users(id),
18+
provider TEXT NOT NULL,
19+
provider_account_id TEXT NOT NULL,
20+
access_token_encrypted TEXT,
21+
refresh_token_encrypted TEXT,
22+
token_type TEXT,
23+
scope TEXT,
24+
expires_at TEXT,
25+
created_at TEXT NOT NULL,
26+
updated_at TEXT NOT NULL,
27+
UNIQUE (provider, provider_account_id)
28+
);
29+
30+
CREATE TABLE IF NOT EXISTS sessions (
31+
id TEXT PRIMARY KEY,
32+
user_id TEXT NOT NULL REFERENCES users(id),
33+
session_token_hash TEXT NOT NULL UNIQUE,
34+
expires_at TEXT NOT NULL,
35+
revoked_at TEXT,
36+
ip_address TEXT,
37+
user_agent TEXT,
38+
created_at TEXT NOT NULL,
39+
updated_at TEXT NOT NULL
40+
);
41+
42+
CREATE TABLE IF NOT EXISTS workspaces (
43+
id TEXT PRIMARY KEY,
44+
slug TEXT NOT NULL UNIQUE,
45+
name TEXT NOT NULL,
46+
kind TEXT NOT NULL,
47+
github_account_type TEXT,
48+
github_account_id TEXT,
49+
created_by_user_id TEXT NOT NULL REFERENCES users(id),
50+
created_at TEXT NOT NULL,
51+
updated_at TEXT NOT NULL
52+
);
53+
54+
CREATE TABLE IF NOT EXISTS workspace_members (
55+
id TEXT PRIMARY KEY,
56+
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
57+
user_id TEXT NOT NULL REFERENCES users(id),
58+
github_user_id TEXT NOT NULL DEFAULT '',
59+
github_login TEXT NOT NULL DEFAULT '',
60+
role TEXT NOT NULL,
61+
status TEXT NOT NULL,
62+
invited_by_user_id TEXT,
63+
created_at TEXT NOT NULL,
64+
updated_at TEXT NOT NULL,
65+
UNIQUE (workspace_id, user_id)
66+
);
67+
68+
CREATE TABLE IF NOT EXISTS workspace_invites (
69+
id TEXT PRIMARY KEY,
70+
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
71+
invite_token_hash TEXT NOT NULL UNIQUE,
72+
invitee_github_login TEXT,
73+
invitee_email TEXT,
74+
role TEXT NOT NULL,
75+
status TEXT NOT NULL,
76+
invited_by_user_id TEXT NOT NULL REFERENCES users(id),
77+
accepted_by_user_id TEXT,
78+
expires_at TEXT NOT NULL,
79+
created_at TEXT NOT NULL,
80+
updated_at TEXT NOT NULL
81+
);
82+
83+
CREATE TABLE IF NOT EXISTS github_installations (
84+
id TEXT PRIMARY KEY,
85+
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
86+
installation_id TEXT NOT NULL,
87+
account_type TEXT NOT NULL,
88+
account_id TEXT NOT NULL,
89+
account_login TEXT,
90+
created_at TEXT NOT NULL,
91+
updated_at TEXT NOT NULL,
92+
UNIQUE (workspace_id, installation_id)
93+
);
94+
95+
CREATE TABLE IF NOT EXISTS repositories (
96+
id TEXT PRIMARY KEY,
97+
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
98+
provider TEXT NOT NULL,
99+
github_repo_id TEXT,
100+
owner TEXT NOT NULL,
101+
name TEXT NOT NULL,
102+
full_name TEXT NOT NULL,
103+
installation_id TEXT,
104+
default_branch TEXT,
105+
is_private INTEGER NOT NULL DEFAULT 0,
106+
is_active INTEGER NOT NULL DEFAULT 1,
107+
created_at TEXT NOT NULL,
108+
updated_at TEXT NOT NULL,
109+
UNIQUE (workspace_id, full_name)
110+
);
111+
112+
CREATE TABLE IF NOT EXISTS workspace_rule_defaults (
113+
workspace_id TEXT PRIMARY KEY REFERENCES workspaces(id),
114+
schema_version INTEGER NOT NULL,
115+
fail_on_findings INTEGER NOT NULL,
116+
fail_on_severity TEXT NOT NULL,
117+
max_inline_findings INTEGER NOT NULL,
118+
min_inline_severity TEXT NOT NULL,
119+
review_tone TEXT NOT NULL,
120+
blocked_patterns TEXT NOT NULL,
121+
required_checks TEXT NOT NULL,
122+
severity_thresholds TEXT NOT NULL,
123+
updated_by_user_id TEXT,
124+
updated_at TEXT NOT NULL
125+
);
126+
127+
CREATE TABLE IF NOT EXISTS repository_rule_overrides (
128+
repository_id TEXT PRIMARY KEY REFERENCES repositories(id),
129+
schema_version INTEGER NOT NULL,
130+
fail_on_findings INTEGER NOT NULL,
131+
fail_on_severity TEXT NOT NULL,
132+
max_inline_findings INTEGER NOT NULL,
133+
min_inline_severity TEXT NOT NULL,
134+
review_tone TEXT NOT NULL,
135+
blocked_patterns TEXT NOT NULL,
136+
required_checks TEXT NOT NULL,
137+
severity_thresholds TEXT NOT NULL,
138+
updated_by_user_id TEXT,
139+
updated_at TEXT NOT NULL
140+
);
141+
142+
CREATE TABLE IF NOT EXISTS pull_requests (
143+
id TEXT PRIMARY KEY,
144+
repository_id TEXT NOT NULL REFERENCES repositories(id),
145+
github_pr_id TEXT,
146+
pr_number INTEGER NOT NULL,
147+
title TEXT,
148+
author_github_login TEXT,
149+
base_ref TEXT,
150+
head_ref TEXT,
151+
head_sha TEXT,
152+
state TEXT NOT NULL,
153+
is_agent_authored INTEGER NOT NULL DEFAULT 0,
154+
agent_name TEXT,
155+
merged_at TEXT,
156+
closed_at TEXT,
157+
created_at TEXT NOT NULL,
158+
updated_at TEXT NOT NULL,
159+
UNIQUE (repository_id, pr_number)
160+
);
161+
162+
CREATE TABLE IF NOT EXISTS review_runs (
163+
id TEXT PRIMARY KEY,
164+
repository_id TEXT NOT NULL REFERENCES repositories(id),
165+
pull_request_id TEXT REFERENCES pull_requests(id),
166+
pr_number INTEGER NOT NULL,
167+
trigger_source TEXT NOT NULL,
168+
status TEXT NOT NULL,
169+
head_sha TEXT,
170+
score_version TEXT NOT NULL,
171+
score_composite REAL,
172+
findings_count INTEGER,
173+
review_mode TEXT NOT NULL DEFAULT 'standard',
174+
review_action TEXT NOT NULL DEFAULT 'COMMENT',
175+
parent_review_run_id TEXT REFERENCES review_runs(id),
176+
started_at TEXT,
177+
completed_at TEXT,
178+
error_message TEXT
179+
);
180+
181+
CREATE TABLE IF NOT EXISTS review_findings (
182+
id TEXT PRIMARY KEY,
183+
review_run_id TEXT NOT NULL REFERENCES review_runs(id),
184+
severity TEXT NOT NULL,
185+
title TEXT NOT NULL,
186+
summary TEXT NOT NULL,
187+
suggestion TEXT,
188+
file_path TEXT,
189+
line INTEGER,
190+
confidence REAL,
191+
status TEXT NOT NULL DEFAULT 'open',
192+
finding_fingerprint TEXT,
193+
created_at TEXT NOT NULL
194+
);
195+
196+
CREATE TABLE IF NOT EXISTS indexing_runs (
197+
id TEXT PRIMARY KEY,
198+
repository_id TEXT NOT NULL REFERENCES repositories(id),
199+
source_ref TEXT,
200+
status TEXT NOT NULL,
201+
summary TEXT,
202+
started_at TEXT,
203+
completed_at TEXT,
204+
error_message TEXT
205+
);
206+
207+
CREATE TABLE IF NOT EXISTS webhook_events (
208+
id TEXT PRIMARY KEY,
209+
provider TEXT NOT NULL,
210+
event TEXT NOT NULL,
211+
delivery_id TEXT NOT NULL,
212+
signature_256 TEXT,
213+
signature_valid INTEGER NOT NULL,
214+
processing_status TEXT NOT NULL,
215+
payload TEXT,
216+
received_at TEXT NOT NULL,
217+
processed_at TEXT,
218+
UNIQUE (provider, delivery_id)
219+
);
220+
221+
CREATE TABLE IF NOT EXISTS audit_logs (
222+
id TEXT PRIMARY KEY,
223+
workspace_id TEXT,
224+
actor_user_id TEXT,
225+
action TEXT NOT NULL,
226+
resource_type TEXT NOT NULL,
227+
resource_id TEXT,
228+
metadata TEXT NOT NULL,
229+
request_id TEXT,
230+
created_at TEXT NOT NULL
231+
);
232+
233+
CREATE TABLE IF NOT EXISTS workspace_secrets (
234+
id TEXT PRIMARY KEY,
235+
workspace_id TEXT NOT NULL REFERENCES workspaces(id),
236+
kind TEXT NOT NULL,
237+
key_id TEXT,
238+
encrypted_value TEXT NOT NULL,
239+
created_by_user_id TEXT,
240+
created_at TEXT NOT NULL,
241+
updated_at TEXT NOT NULL,
242+
UNIQUE (workspace_id, kind)
243+
);
244+
245+
CREATE TABLE IF NOT EXISTS indexed_files (
246+
id TEXT PRIMARY KEY,
247+
repository_id TEXT NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
248+
source_ref TEXT NOT NULL,
249+
path TEXT NOT NULL,
250+
blob_sha TEXT NOT NULL,
251+
content_sha256 TEXT NOT NULL,
252+
language TEXT NOT NULL,
253+
size_bytes INTEGER NOT NULL DEFAULT 0,
254+
chunk_strategy TEXT NOT NULL DEFAULT 'tree-sitter',
255+
indexed_at TEXT NOT NULL DEFAULT (datetime('now')),
256+
UNIQUE (repository_id, source_ref, path)
257+
);
258+
259+
CREATE TABLE IF NOT EXISTS semantic_chunks (
260+
id TEXT PRIMARY KEY,
261+
repository_id TEXT NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
262+
source_ref TEXT NOT NULL,
263+
file_path TEXT NOT NULL,
264+
file_content_sha256 TEXT NOT NULL,
265+
language TEXT NOT NULL,
266+
symbol_kind TEXT NOT NULL DEFAULT 'unknown',
267+
symbol_name TEXT,
268+
chunk_ordinal INTEGER NOT NULL DEFAULT 0,
269+
start_line INTEGER NOT NULL,
270+
end_line INTEGER NOT NULL,
271+
content TEXT NOT NULL,
272+
content_sha256 TEXT NOT NULL,
273+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
274+
);
275+
276+
-- Indexes
277+
CREATE INDEX IF NOT EXISTS idx_workspace_members_workspace ON workspace_members(workspace_id);
278+
CREATE INDEX IF NOT EXISTS idx_repositories_workspace ON repositories(workspace_id);
279+
CREATE INDEX IF NOT EXISTS idx_pull_requests_repository ON pull_requests(repository_id);
280+
CREATE INDEX IF NOT EXISTS idx_review_runs_repository ON review_runs(repository_id);
281+
CREATE INDEX IF NOT EXISTS idx_review_findings_run ON review_findings(review_run_id);
282+
CREATE INDEX IF NOT EXISTS idx_indexing_runs_repository ON indexing_runs(repository_id);
283+
CREATE INDEX IF NOT EXISTS idx_audit_logs_workspace ON audit_logs(workspace_id, created_at);
284+
CREATE INDEX IF NOT EXISTS idx_review_runs_parent ON review_runs(parent_review_run_id) WHERE parent_review_run_id IS NOT NULL;
285+
CREATE INDEX IF NOT EXISTS idx_review_findings_fingerprint ON review_findings(finding_fingerprint) WHERE finding_fingerprint IS NOT NULL;
286+
CREATE INDEX IF NOT EXISTS idx_indexed_files_repo ON indexed_files(repository_id);
287+
CREATE INDEX IF NOT EXISTS idx_indexed_files_repo_ref ON indexed_files(repository_id, source_ref);
288+
CREATE INDEX IF NOT EXISTS idx_semantic_chunks_repo ON semantic_chunks(repository_id);
289+
CREATE INDEX IF NOT EXISTS idx_semantic_chunks_repo_ref ON semantic_chunks(repository_id, source_ref);
290+
CREATE INDEX IF NOT EXISTS idx_semantic_chunks_symbol ON semantic_chunks(symbol_name) WHERE symbol_name IS NOT NULL;

0 commit comments

Comments
 (0)