import { pgTable, serial, text, timestamp, integer } from 'drizzle-orm/pg-core'; /** * The connection to Nginx Proxy Manager. * * ── Why its own table rather than core `service_connections` ── * * `service_connections` fits the shape exactly — it has `url`, `username` and an encrypted `secret`. But * its `ServiceName` is a closed TypeScript union, so using it means editing the platform to add a name, * and this plugin is meant to install into a platform it did not change. The table comment there already * says the column is text precisely so adding a service is not a schema change; the union is the part * that has not caught up. * * Revisit if that union opens. Until then the cost is one small table and one encryption purpose. * * ── One row, not one per user ── * * NPM has no read-only role. Its API is admin or nothing, so a per-user credential would be a per-user * copy of the same total authority over every hostname this machine serves. There is one connection, the * owner sets it, and members granted the permission read through it without ever seeing it. */ export const proxyManagerConnection = pgTable('proxy_manager_connection', { id: serial('id').primaryKey(), /** Where NPM's admin API is. Normalised without a trailing slash before write. */ url: text('url').notNull(), /** NPM calls it `identity`; it is an email address. */ identity: text('identity').notNull(), /** * Encrypted with `encryptSecret('proxy-manager', …)` — its own purpose key, so a leak of this one * opens this plugin's column and nothing else. Never returned across the API boundary, at any level, * to anybody, including the owner. */ secret: text('secret').notNull(), /** From `GET /api/`, recorded on a successful probe. Tells you which NPM you are talking to. */ version: text('version'), lastProbeAt: timestamp('last_probe_at', { withTimezone: true }), lastProbeOk: integer('last_probe_ok'), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }); export type ProxyManagerConnection = typeof proxyManagerConnection.$inferSelect;