diff --git a/packages/db/src/migrations/0219_runtime_service_exposure.sql b/packages/db/src/migrations/0219_runtime_service_exposure.sql new file mode 100644 index 00000000000..686c18c25de --- /dev/null +++ b/packages/db/src/migrations/0219_runtime_service_exposure.sql @@ -0,0 +1 @@ +ALTER TABLE "workspace_runtime_services" ADD COLUMN "exposure" jsonb; diff --git a/packages/db/src/migrations/meta/_journal.json b/packages/db/src/migrations/meta/_journal.json index e8ee2e3ee30..fd7a9ef3050 100644 --- a/packages/db/src/migrations/meta/_journal.json +++ b/packages/db/src/migrations/meta/_journal.json @@ -1520,6 +1520,13 @@ "when": 1786711898729, "tag": "0218_mushy_jack_murdock", "breakpoints": true + }, + { + "idx": 219, + "version": "7", + "when": 1786908241945, + "tag": "0219_runtime_service_exposure", + "breakpoints": true } ] -} \ No newline at end of file +} diff --git a/packages/db/src/schema/workspace_runtime_services.ts b/packages/db/src/schema/workspace_runtime_services.ts index 150c332dec8..405b0d5d4ab 100644 --- a/packages/db/src/schema/workspace_runtime_services.ts +++ b/packages/db/src/schema/workspace_runtime_services.ts @@ -7,6 +7,7 @@ import { timestamp, uuid, } from "drizzle-orm/pg-core"; +import type { RuntimeExposureStatus } from "@paperclipai/shared"; import { companies } from "./companies.js"; import { projects } from "./projects.js"; import { projectWorkspaces } from "./project_workspaces.js"; @@ -42,6 +43,11 @@ export const workspaceRuntimeServices = pgTable( startedAt: timestamp("started_at", { withTimezone: true }).notNull().defaultNow(), stoppedAt: timestamp("stopped_at", { withTimezone: true }), stopPolicy: jsonb("stop_policy").$type>(), + // Structured opt-in `tailscale_https` exposure state (PAP-17049/17050). + // Null when the service is not configured for HTTPS exposure. Modelled + // independently of process `status`/`healthStatus` so HTTPS provisioning / + // failure / cleanup surface separately from backend process health. + exposure: jsonb("exposure").$type(), healthStatus: text("health_status").notNull().default("unknown"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),