swadhinbiswas feat: finalize platform polish - discussions, gists, webhook queue, realtime, push-mirror, auth/metrics hardening · 8/28/2026
f02976d
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
/**
* Webhooks Schema - Drizzle ORM
* Defines webhooks and delivery logs
*/
import { relations } from "drizzle-orm";
import {
boolean,
index,
integer,
pgTable,
text,
timestamp,
} from "drizzle-orm/pg-core";
import { repositories } from "./repositories";
import { users } from "./users";
export const webhooks = pgTable(
"webhooks",
{
id: text("id").primaryKey(),
repositoryId: text("repository_id")
.notNull()
.references(() => repositories.id, { onDelete: "cascade" }),
// Provider and configuration
provider: text("provider").default("generic"), // teams, discord, slack, generic, linear, trello, clickup
name: text("name"), // Display name for the webhook
url: text("url").notNull(),
secret: text("secret"), // Encrypted or plain? For now plain/masked in UI
events: text("events").notNull(), // JSON array of events ['push', 'pull_request']
active: boolean("active").notNull().default(true),
enabled: boolean("enabled").notNull().default(true), // Alias for active
contentType: text("content_type").notNull().default("json"), // json | form
// Stats
deliveryCount: integer("delivery_count").default(0),
lastDeliveryStatus: text("last_delivery_status"), // success | failure
lastDeliveryAt: timestamp("last_delivery_at"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
createdById: text("created_by_id").references(() => users.id),
},
(t) => ({
repoIdx: index("webhooks_repo_idx").on(t.repositoryId),
}),
);
export const webhookDeliveries = pgTable(
"webhook_deliveries",
{
id: text("id").primaryKey(),
webhookId: text("webhook_id")
.notNull()
.references(() => webhooks.id, { onDelete: "cascade" }),
event: text("event").notNull(),
payload: text("payload").notNull(), // JSON
// Queue lifecycle: pending | processing | delivered | dead.
// Legacy rows (pre-queue) may still carry success | failure.
status: text("status").notNull(),
attempts: integer("attempts").notNull().default(0),
nextAttemptAt: timestamp("next_attempt_at"),
lockedAt: timestamp("locked_at"),
failureReason: text("failure_reason"),
responseCode: integer("response_code"),
responseBody: text("response_body"),
durationMs: integer("duration_ms"),
error: text("error"),
requestHeaders: text("request_headers"), // JSON
responseHeaders: text("response_headers"), // JSON
createdAt: timestamp("created_at").notNull().defaultNow(),
},
(t) => ({
webhookIdx: index("webhook_deliveries_webhook_idx").on(t.webhookId),
createdAtIdx: index("webhook_deliveries_created_idx").on(t.createdAt),
queueIdx: index("webhook_deliveries_queue_idx").on(t.status, t.nextAttemptAt),
}),
);
export const webhooksRelations = relations(webhooks, ({ one, many }) => ({
repository: one(repositories, {
fields: [webhooks.repositoryId],
references: [repositories.id],
}),
createdBy: one(users, {
fields: [webhooks.createdById],
references: [users.id],
}),
deliveries: many(webhookDeliveries),
}));
export const webhookDeliveriesRelations = relations(
webhookDeliveries,
({ one }) => ({
webhook: one(webhooks, {
fields: [webhookDeliveries.webhookId],
references: [webhooks.id],
}),
}),
);