deep research addressement

This commit is contained in:
2026-06-01 08:40:10 -04:00
parent c159f07322
commit ba73daa66c
205 changed files with 157390 additions and 951 deletions

View File

@@ -44,6 +44,107 @@ export const removalRequests = sqliteTable("removal_requests", {
subscriptionIdStatusIdx: index("removal_requests_sub_id_status_idx").on(table.subscriptionId, table.status),
}));
export const captchaEvents = sqliteTable("captcha_events", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
removalRequestId: text("removal_request_id").references(() => removalRequests.id, { onDelete: "set null" }),
brokerId: text("broker_id").notNull().references(() => infoBrokers.id, { onDelete: "cascade" }),
captchaType: text("captcha_type").notNull(), // recaptcha_v2, recaptcha_v3, hcaptcha, image_challenge, turnstile
status: text("status").notNull().default("detected"), // detected, solving, solved, failed, escalated
solverProvider: text("solver_provider"), // 2captcha, anticaptcha, manual
solveAttempts: integer("solve_attempts").default(0).notNull(),
costInCents: integer("cost_in_cents"),
error: text("error"),
solvedAt: integer("solved_at", { mode: "timestamp_ms" }),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).defaultNow().notNull().$onUpdate(() => new Date()),
}, (table) => ({
removalRequestIdIdx: index("captcha_events_removal_request_id_idx").on(table.removalRequestId),
brokerIdIdx: index("captcha_events_broker_id_idx").on(table.brokerId),
statusIdx: index("captcha_events_status_idx").on(table.status),
createdAtIdx: index("captcha_events_created_at_idx").on(table.createdAt),
}));
export const emailVerifications = sqliteTable("email_verifications", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
removalRequestId: text("removal_request_id").references(() => removalRequests.id, { onDelete: "set null" }),
brokerId: text("broker_id").notNull().references(() => infoBrokers.id, { onDelete: "cascade" }),
emailTo: text("email_to").notNull(),
emailFrom: text("email_from"),
emailSubject: text("email_subject"),
confirmationUrl: text("confirmation_url"),
status: text("status").notNull().default("pending"), // pending, confirmed, expired, failed
clickedAt: integer("clicked_at", { mode: "timestamp_ms" }),
confirmedAt: integer("confirmed_at", { mode: "timestamp_ms" }),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).defaultNow().notNull().$onUpdate(() => new Date()),
}, (table) => ({
removalRequestIdIdx: index("email_verifications_removal_request_id_idx").on(table.removalRequestId),
brokerIdIdx: index("email_verifications_broker_id_idx").on(table.brokerId),
statusIdx: index("email_verifications_status_idx").on(table.status),
createdAtIdx: index("email_verifications_created_at_idx").on(table.createdAt),
emailToIdx: index("email_verifications_email_to_idx").on(table.emailTo),
}));
export const reScanResults = sqliteTable("re_scan_results", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
subscriptionId: text("subscription_id").notNull().references(() => subscriptions.id, { onDelete: "cascade" }),
brokerId: text("broker_id").notNull(),
removalRequestId: text("removal_request_id").references(() => removalRequests.id, { onDelete: "set null" }),
wasRemoved: integer("was_removed", { mode: "boolean" }).notNull(),
isReListed: integer("is_re_listed", { mode: "boolean" }).default(false).notNull(),
profileUrl: text("profile_url"),
scanType: text("scan_type").notNull(), // initial_scan, status_check, weekly_rescan, re_listing_detected
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
}, (table) => ({
subscriptionIdIdx: index("re_scan_results_subscription_id_idx").on(table.subscriptionId),
brokerIdIdx: index("re_scan_results_broker_id_idx").on(table.brokerId),
isReListedIdx: index("re_scan_results_is_re_listed_idx").on(table.isReListed),
scanTypeIdx: index("re_scan_results_scan_type_idx").on(table.scanType),
createdAtIdx: index("re_scan_results_created_at_idx").on(table.createdAt),
}));
export const adapterHealth = sqliteTable("adapter_health", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
brokerId: text("broker_id").notNull().references(() => infoBrokers.id, { onDelete: "cascade" }),
brokerName: text("broker_name").notNull(),
status: text("status").notNull().default("healthy"), // healthy, degraded, broken, disabled
successCount: integer("success_count").default(0).notNull(),
failureCount: integer("failure_count").default(0).notNull(),
lastSuccessAt: integer("last_success_at", { mode: "timestamp_ms" }),
lastFailureAt: integer("last_failure_at", { mode: "timestamp_ms" }),
lastError: text("last_error"),
failureRate24h: integer("failure_rate_24h"),
totalOps24h: integer("total_ops_24h").default(0),
isAutoDisabled: integer("is_auto_disabled", { mode: "boolean" }).default(false).notNull(),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).defaultNow().notNull().$onUpdate(() => new Date()),
}, (table) => ({
brokerIdIdx: index("adapter_health_broker_id_idx").on(table.brokerId),
statusIdx: index("adapter_health_status_idx").on(table.status),
isAutoDisabledIdx: index("adapter_health_is_auto_disabled_idx").on(table.isAutoDisabled),
failureRate24hIdx: index("adapter_health_failure_rate_24h_idx").on(table.failureRate24h),
}));
export const costTracking = sqliteTable("cost_tracking", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
subscriptionId: text("subscription_id").references(() => subscriptions.id, { onDelete: "set null" }),
proxyProvider: text("proxy_provider"),
captchaSolver: text("captcha_solver"),
proxyRequests: integer("proxy_requests").default(0).notNull(),
captchaSolves: integer("captcha_solves").default(0).notNull(),
captchaCostCents: integer("captcha_cost_cents").default(0).notNull(),
proxyCostCents: integer("proxy_cost_cents").default(0).notNull(),
totalCostCents: integer("total_cost_cents").default(0).notNull(),
periodStart: integer("period_start", { mode: "timestamp_ms" }).notNull(),
periodEnd: integer("period_end", { mode: "timestamp_ms" }).notNull(),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
}, (table) => ({
subscriptionIdIdx: index("cost_tracking_subscription_id_idx").on(table.subscriptionId),
periodStartIdx: index("cost_tracking_period_start_idx").on(table.periodStart),
periodEndIdx: index("cost_tracking_period_end_idx").on(table.periodEnd),
}));
export const brokerListings = sqliteTable("broker_listings", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
subscriptionId: text("subscription_id").notNull().references(() => subscriptions.id, { onDelete: "cascade" }),