import { pgTable, uuid, text, timestamp, jsonb, index, } from "drizzle-orm/pg-core"; import { companies } from "./companies.js"; import { plugins } from "./plugins.js"; /** * `plugin_logs` table โ€” structured log storage for plugin workers. * * Each row stores a single log entry emitted by a plugin worker via * `ctx.logger.info(...)` etc. Logs are queryable by plugin, level, and * time range to support the operator logs panel and debugging workflows. * * Rows are inserted by the host when handling `log` notifications from * the worker process. A capped retention policy can be applied via * periodic cleanup (e.g. delete rows older than 7 days). * * @see PLUGIN_SPEC.md ยง26 โ€” Observability */ export const pluginLogs = pgTable( "plugin_logs", { id: uuid("id").primaryKey().defaultRandom(), pluginId: uuid("plugin_id") .notNull() .references(() => plugins.id, { onDelete: "cascade" }), /** Company scope โ€” NULL for instance-level logs. */ companyId: uuid("company_id").references(() => companies.id, { onDelete: "cascade" }), level: text("level").notNull().default("info"), message: text("message").notNull(), meta: jsonb("meta").$type>(), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ pluginTimeIdx: index("plugin_logs_plugin_time_idx").on( table.pluginId, table.createdAt, ), companyIdx: index("plugin_logs_company_idx").on(table.companyId), levelIdx: index("plugin_logs_level_idx").on(table.level), }), );