openship 0.1.0 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +5786 -0
  3. package/dist/server/index.js +324319 -0
  4. package/dist/server/migrations/0000_init.sql +666 -0
  5. package/dist/server/migrations/0001_brief_tomorrow_man.sql +47 -0
  6. package/dist/server/migrations/0002_funny_dazzler.sql +2 -0
  7. package/dist/server/migrations/0003_third_killer_shrike.sql +1 -0
  8. package/dist/server/migrations/0004_session_active_org_not_null.sql +10 -0
  9. package/dist/server/migrations/0005_warm_amazoness.sql +3 -0
  10. package/dist/server/migrations/0006_lumpy_joystick.sql +1 -0
  11. package/dist/server/migrations/0007_outgoing_maginty.sql +2 -0
  12. package/dist/server/migrations/0008_frozen_cutover.sql +3 -0
  13. package/dist/server/migrations/0009_credits_billing.sql +142 -0
  14. package/dist/server/migrations/0010_credit_grant_dedupe.sql +14 -0
  15. package/dist/server/migrations/0011_remove_credit_ledger.sql +23 -0
  16. package/dist/server/migrations/0012_smart_deploys_and_git_rollback.sql +81 -0
  17. package/dist/server/migrations/0013_fix_check_run_rollup_unique.sql +38 -0
  18. package/dist/server/migrations/0014_default_rollback_git.sql +9 -0
  19. package/dist/server/migrations/0015_billing_idempotency_grants.sql +41 -0
  20. package/dist/server/migrations/0016_github_auth_high_findings.sql +30 -0
  21. package/dist/server/migrations/0017_spooky_rumiko_fujikawa.sql +6 -0
  22. package/dist/server/migrations/0018_calm_shatterstar.sql +1 -0
  23. package/dist/server/migrations/0019_rename_workspace_install_to_prepare.sql +1 -0
  24. package/dist/server/migrations/0020_uneven_the_renegades.sql +13 -0
  25. package/dist/server/migrations/0021_shiny_firestar.sql +2 -0
  26. package/dist/server/migrations/0022_version_on_success_backfill.sql +6 -0
  27. package/dist/server/migrations/0023_productive_gorilla_man.sql +17 -0
  28. package/dist/server/migrations/0024_sleepy_peter_quill.sql +2 -0
  29. package/dist/server/migrations/0025_smooth_blue_shield.sql +1 -0
  30. package/dist/server/migrations/0026_mail_backup_source.sql +11 -0
  31. package/dist/server/migrations/0027_opposite_anthem.sql +6 -0
  32. package/dist/server/migrations/0028_stale_rogue.sql +18 -0
  33. package/dist/server/migrations/0029_bouncy_loners.sql +16 -0
  34. package/dist/server/migrations/0030_bright_darkstar.sql +6 -0
  35. package/dist/server/migrations/0031_conscious_catseye.sql +13 -0
  36. package/dist/server/migrations/0032_wet_mimic.sql +51 -0
  37. package/dist/server/migrations/0033_eminent_molly_hayes.sql +2 -0
  38. package/dist/server/migrations/meta/0000_snapshot.json +5110 -0
  39. package/dist/server/migrations/meta/0001_snapshot.json +5257 -0
  40. package/dist/server/migrations/meta/0002_snapshot.json +5279 -0
  41. package/dist/server/migrations/meta/0003_snapshot.json +5286 -0
  42. package/dist/server/migrations/meta/0004_snapshot.json +5286 -0
  43. package/dist/server/migrations/meta/0005_snapshot.json +5305 -0
  44. package/dist/server/migrations/meta/0006_snapshot.json +5311 -0
  45. package/dist/server/migrations/meta/0007_snapshot.json +5323 -0
  46. package/dist/server/migrations/meta/0016_snapshot.json +6345 -0
  47. package/dist/server/migrations/meta/0017_snapshot.json +6383 -0
  48. package/dist/server/migrations/meta/0018_snapshot.json +6390 -0
  49. package/dist/server/migrations/meta/0019_snapshot.json +6390 -0
  50. package/dist/server/migrations/meta/0020_snapshot.json +6497 -0
  51. package/dist/server/migrations/meta/0021_snapshot.json +6509 -0
  52. package/dist/server/migrations/meta/0022_snapshot.json +6509 -0
  53. package/dist/server/migrations/meta/0023_snapshot.json +6629 -0
  54. package/dist/server/migrations/meta/0024_snapshot.json +6641 -0
  55. package/dist/server/migrations/meta/0025_snapshot.json +6648 -0
  56. package/dist/server/migrations/meta/0026_snapshot.json +6750 -0
  57. package/dist/server/migrations/meta/0027_snapshot.json +6757 -0
  58. package/dist/server/migrations/meta/0028_snapshot.json +6895 -0
  59. package/dist/server/migrations/meta/0029_snapshot.json +7028 -0
  60. package/dist/server/migrations/meta/0030_snapshot.json +7066 -0
  61. package/dist/server/migrations/meta/0031_snapshot.json +7181 -0
  62. package/dist/server/migrations/meta/0032_snapshot.json +7570 -0
  63. package/dist/server/migrations/meta/0033_snapshot.json +7597 -0
  64. package/dist/server/migrations/meta/_journal.json +244 -0
  65. package/dist/server/pglite/pglite.data +0 -0
  66. package/dist/server/pglite/pglite.wasm +0 -0
  67. package/package.json +33 -21
  68. package/.env.example +0 -22
  69. package/.nvmrc +0 -1
  70. package/.prettierrc +0 -7
  71. package/CONTRIBUTING.md +0 -40
  72. package/README.md +0 -164
  73. package/apps/api/.env.example +0 -30
  74. package/apps/api/Dockerfile +0 -24
  75. package/apps/api/package.json +0 -37
  76. package/apps/api/src/app.ts +0 -26
  77. package/apps/api/src/config/env.ts +0 -39
  78. package/apps/api/src/config/index.ts +0 -1
  79. package/apps/api/src/index.ts +0 -8
  80. package/apps/api/src/middleware/auth.ts +0 -24
  81. package/apps/api/src/middleware/error-handler.ts +0 -21
  82. package/apps/api/src/middleware/index.ts +0 -3
  83. package/apps/api/src/middleware/rate-limiter.ts +0 -26
  84. package/apps/api/src/modules/auth/auth.controller.ts +0 -26
  85. package/apps/api/src/modules/auth/auth.routes.ts +0 -10
  86. package/apps/api/src/modules/auth/auth.schema.ts +0 -12
  87. package/apps/api/src/modules/auth/auth.service.ts +0 -23
  88. package/apps/api/src/modules/billing/billing.controller.ts +0 -60
  89. package/apps/api/src/modules/billing/billing.routes.ts +0 -26
  90. package/apps/api/src/modules/billing/billing.schema.ts +0 -9
  91. package/apps/api/src/modules/billing/billing.service.ts +0 -33
  92. package/apps/api/src/modules/deployments/deployment.controller.ts +0 -35
  93. package/apps/api/src/modules/deployments/deployment.routes.ts +0 -11
  94. package/apps/api/src/modules/deployments/deployment.schema.ts +0 -7
  95. package/apps/api/src/modules/deployments/deployment.service.ts +0 -23
  96. package/apps/api/src/modules/domains/domain.controller.ts +0 -21
  97. package/apps/api/src/modules/domains/domain.routes.ts +0 -9
  98. package/apps/api/src/modules/domains/domain.service.ts +0 -19
  99. package/apps/api/src/modules/health/health.routes.ts +0 -10
  100. package/apps/api/src/modules/projects/project.controller.ts +0 -29
  101. package/apps/api/src/modules/projects/project.routes.ts +0 -10
  102. package/apps/api/src/modules/projects/project.schema.ts +0 -9
  103. package/apps/api/src/modules/projects/project.service.ts +0 -23
  104. package/apps/api/src/modules/webhooks/webhook.controller.ts +0 -22
  105. package/apps/api/src/modules/webhooks/webhook.routes.ts +0 -12
  106. package/apps/api/src/modules/webhooks/webhook.service.ts +0 -11
  107. package/apps/api/tsconfig.json +0 -12
  108. package/apps/cli/package.json +0 -28
  109. package/apps/cli/src/commands/deploy.ts +0 -11
  110. package/apps/cli/src/commands/init.ts +0 -8
  111. package/apps/cli/src/commands/login.ts +0 -8
  112. package/apps/cli/src/commands/logs.ts +0 -9
  113. package/apps/cli/src/index.ts +0 -21
  114. package/apps/cli/src/lib/api-client.ts +0 -35
  115. package/apps/cli/tsconfig.json +0 -12
  116. package/apps/dashboard/Dockerfile +0 -24
  117. package/apps/dashboard/next.config.mjs +0 -6
  118. package/apps/dashboard/package.json +0 -28
  119. package/apps/dashboard/src/app/(auth)/layout.tsx +0 -6
  120. package/apps/dashboard/src/app/(auth)/login/page.tsx +0 -11
  121. package/apps/dashboard/src/app/(auth)/register/page.tsx +0 -10
  122. package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +0 -10
  123. package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +0 -8
  124. package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +0 -8
  125. package/apps/dashboard/src/app/(dashboard)/layout.tsx +0 -37
  126. package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +0 -8
  127. package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +0 -8
  128. package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +0 -8
  129. package/apps/dashboard/src/app/globals.css +0 -3
  130. package/apps/dashboard/src/app/layout.tsx +0 -15
  131. package/apps/dashboard/src/app/page.tsx +0 -6
  132. package/apps/dashboard/tsconfig.json +0 -11
  133. package/apps/web/Dockerfile +0 -24
  134. package/apps/web/next.config.mjs +0 -6
  135. package/apps/web/package.json +0 -26
  136. package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
  137. package/apps/web/src/app/(marketing)/layout.tsx +0 -24
  138. package/apps/web/src/app/(marketing)/page.tsx +0 -2
  139. package/apps/web/src/app/(marketing)/pricing/page.tsx +0 -10
  140. package/apps/web/src/app/globals.css +0 -3
  141. package/apps/web/src/app/layout.tsx +0 -16
  142. package/apps/web/src/app/page.tsx +0 -10
  143. package/apps/web/tsconfig.json +0 -11
  144. package/docker-compose.yml +0 -87
  145. package/packages/adapters/package.json +0 -27
  146. package/packages/adapters/src/base-adapter.ts +0 -49
  147. package/packages/adapters/src/docker-adapter.ts +0 -43
  148. package/packages/adapters/src/index.ts +0 -4
  149. package/packages/adapters/src/oblien-adapter.ts +0 -46
  150. package/packages/adapters/src/registry.ts +0 -22
  151. package/packages/adapters/tsconfig.json +0 -9
  152. package/packages/core/package.json +0 -27
  153. package/packages/core/src/constants.ts +0 -28
  154. package/packages/core/src/errors.ts +0 -49
  155. package/packages/core/src/index.ts +0 -4
  156. package/packages/core/src/types.ts +0 -47
  157. package/packages/core/src/utils.ts +0 -35
  158. package/packages/core/tsconfig.json +0 -9
  159. package/packages/db/package.json +0 -32
  160. package/packages/db/prisma/schema.prisma +0 -160
  161. package/packages/db/src/index.ts +0 -11
  162. package/packages/db/tsconfig.json +0 -9
  163. package/packages/ui/package.json +0 -38
  164. package/packages/ui/src/components/badge.tsx +0 -29
  165. package/packages/ui/src/components/button.tsx +0 -44
  166. package/packages/ui/src/components/card.tsx +0 -26
  167. package/packages/ui/src/components/status-dot.tsx +0 -25
  168. package/packages/ui/src/globals.css +0 -18
  169. package/packages/ui/src/index.tsx +0 -8
  170. package/packages/ui/src/lib/cn.ts +0 -7
  171. package/packages/ui/tsconfig.json +0 -9
  172. package/pnpm-workspace.yaml +0 -4
  173. package/tooling/tsconfig/base.json +0 -19
  174. package/tooling/tsconfig/nextjs.json +0 -10
  175. package/tooling/tsconfig/node.json +0 -10
  176. package/tooling/tsconfig/package.json +0 -7
  177. package/turbo.json +0 -32
@@ -0,0 +1,47 @@
1
+ -- Schema hardening: drop legacy organization_meta (folded into organization.is_team),
2
+ -- add missing FKs + indexes flagged by the enterprise audit, and the partial
3
+ -- unique index that race-guards concurrent deployment creation.
4
+ --
5
+ -- All statements are idempotent so re-running on DBs already partway through
6
+ -- the consolidation succeeds. Greenfield installs apply the same SQL with the
7
+ -- IF (NOT) EXISTS guards as no-op when conditions are met.
8
+
9
+ DROP TABLE IF EXISTS "organization_meta" CASCADE;--> statement-breakpoint
10
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "is_team" boolean DEFAULT false NOT NULL;--> statement-breakpoint
11
+
12
+ -- FK: domain.service_id → service.id (CASCADE delete to prevent stale routing)
13
+ DO $$ BEGIN
14
+ ALTER TABLE "domain" ADD CONSTRAINT "domain_service_id_service_id_fk"
15
+ FOREIGN KEY ("service_id") REFERENCES "public"."service"("id") ON DELETE cascade ON UPDATE no action;
16
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
17
+
18
+ -- FK: env_var.service_id → service.id (CASCADE delete to prevent orphan env vars)
19
+ DO $$ BEGIN
20
+ ALTER TABLE "env_var" ADD CONSTRAINT "env_var_service_id_service_id_fk"
21
+ FOREIGN KEY ("service_id") REFERENCES "public"."service"("id") ON DELETE cascade ON UPDATE no action;
22
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
23
+
24
+ -- Race guard: only one in-flight deployment per project. The race-prone
25
+ -- (SELECT-then-INSERT) in build.service.ts now relies on this constraint.
26
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_deployment_one_active_per_project"
27
+ ON "deployment" USING btree ("project_id")
28
+ WHERE status IN ('queued', 'building', 'deploying');--> statement-breakpoint
29
+
30
+ -- Routing hot path — every hostname lookup hits the (project_id) and
31
+ -- (project_id, hostname) indexes.
32
+ CREATE INDEX IF NOT EXISTS "idx_domain_project" ON "domain" USING btree ("project_id");--> statement-breakpoint
33
+ CREATE INDEX IF NOT EXISTS "idx_domain_project_hostname" ON "domain" USING btree ("project_id","hostname");--> statement-breakpoint
34
+
35
+ -- Env var resolution runs on every build.
36
+ CREATE INDEX IF NOT EXISTS "idx_env_var_project_env_service" ON "env_var" USING btree ("project_id","environment","service_id");--> statement-breakpoint
37
+ CREATE INDEX IF NOT EXISTS "idx_env_var_project" ON "env_var" USING btree ("project_id");--> statement-breakpoint
38
+
39
+ -- GitHub App installation lookup: unique (provider, owner, user_id) backs
40
+ -- atomic onConflictDoUpdate; (organization_id, provider, owner) backs the
41
+ -- org-scoped resolution path used by every authed request that mints an
42
+ -- installation token.
43
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_git_installation_provider_owner_user" ON "git_installation" USING btree ("provider","owner","user_id");--> statement-breakpoint
44
+ CREATE INDEX IF NOT EXISTS "idx_git_installation_org" ON "git_installation" USING btree ("organization_id","provider","owner");--> statement-breakpoint
45
+
46
+ -- Build pipeline + deployment setup iterate services per project.
47
+ CREATE INDEX IF NOT EXISTS "idx_service_project_id" ON "service" USING btree ("project_id");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "project" ADD COLUMN IF NOT EXISTS "cloud_workspace_id" text;--> statement-breakpoint
2
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_project_cloud_workspace_id" ON "project" USING btree ("cloud_workspace_id") WHERE "project"."cloud_workspace_id" IS NOT NULL AND "project"."deleted_at" IS NULL;
@@ -0,0 +1 @@
1
+ ALTER TABLE "instance_settings" ADD COLUMN "invitation_mail_source" text DEFAULT 'platform' NOT NULL;
@@ -0,0 +1,10 @@
1
+ -- Backfill any remaining nulls (from sessions created before the
2
+ -- create-time hook landed) to the user's personal org. The
3
+ -- provisionUser convention is org_<userId>, and provisionUser
4
+ -- guarantees that org + owner-member row exist for every user.
5
+ UPDATE "session" SET "active_organization_id" = 'org_' || "user_id"
6
+ WHERE "active_organization_id" IS NULL;
7
+ --> statement-breakpoint
8
+ -- Promote to NOT NULL — the schema itself now enforces the
9
+ -- invariant. No code path can violate it.
10
+ ALTER TABLE "session" ALTER COLUMN "active_organization_id" SET NOT NULL;
@@ -0,0 +1,3 @@
1
+ ALTER TABLE "instance_settings" ADD COLUMN "team_mode" text DEFAULT 'single_user' NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "instance_settings" ADD COLUMN "migration_target_url" text;--> statement-breakpoint
3
+ ALTER TABLE "instance_settings" ADD COLUMN "migrated_at" timestamp;
@@ -0,0 +1 @@
1
+ ALTER TABLE "instance_settings" ADD COLUMN "migration_server_id" text;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "instance_settings" ADD COLUMN "tunnel_slug" text;--> statement-breakpoint
2
+ ALTER TABLE "instance_settings" ADD COLUMN "tunnel_id" text;
@@ -0,0 +1,3 @@
1
+ ALTER TABLE "instance_settings" ADD COLUMN "migration_in_progress" boolean NOT NULL DEFAULT false;
2
+ --> statement-breakpoint
3
+ ALTER TABLE "instance_settings" ADD COLUMN "migration_started_at" timestamp;
@@ -0,0 +1,142 @@
1
+ -- Billing & credits: add per-org plan/subscription columns and the credit
2
+ -- ledger tables. Idempotent (IF NOT EXISTS guards) so applying twice on a
3
+ -- partway-through DB is a no-op.
4
+
5
+ -- ── organization: billing columns ───────────────────────────────────────────
6
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "plan_tier_id" text DEFAULT 'free' NOT NULL;--> statement-breakpoint
7
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "stripe_customer_id" text;--> statement-breakpoint
8
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "subscription_status" text DEFAULT 'active' NOT NULL;--> statement-breakpoint
9
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "current_period_start" timestamp;--> statement-breakpoint
10
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "current_period_end" timestamp;--> statement-breakpoint
11
+ ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "oblien_namespace" text;--> statement-breakpoint
12
+
13
+ -- ── billing_customer ────────────────────────────────────────────────────────
14
+ CREATE TABLE IF NOT EXISTS "billing_customer" (
15
+ "id" text PRIMARY KEY NOT NULL,
16
+ "organization_id" text NOT NULL,
17
+ "stripe_customer_id" text NOT NULL,
18
+ "email" text NOT NULL,
19
+ "created_at" timestamp DEFAULT now() NOT NULL,
20
+ "updated_at" timestamp DEFAULT now() NOT NULL
21
+ );--> statement-breakpoint
22
+
23
+ DO $$ BEGIN
24
+ ALTER TABLE "billing_customer" ADD CONSTRAINT "billing_customer_organization_id_organization_id_fk"
25
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
26
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
27
+
28
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_billing_customer_org" ON "billing_customer" USING btree ("organization_id");--> statement-breakpoint
29
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_billing_customer_stripe" ON "billing_customer" USING btree ("stripe_customer_id");--> statement-breakpoint
30
+
31
+ -- ── billing_subscription ────────────────────────────────────────────────────
32
+ CREATE TABLE IF NOT EXISTS "billing_subscription" (
33
+ "id" text PRIMARY KEY NOT NULL,
34
+ "organization_id" text NOT NULL,
35
+ "stripe_subscription_id" text NOT NULL,
36
+ "stripe_price_id" text NOT NULL,
37
+ "plan_tier_id" text NOT NULL,
38
+ "interval" text NOT NULL,
39
+ "status" text NOT NULL,
40
+ "current_period_start" timestamp NOT NULL,
41
+ "current_period_end" timestamp NOT NULL,
42
+ "cancel_at_period_end" boolean DEFAULT false NOT NULL,
43
+ "created_at" timestamp DEFAULT now() NOT NULL,
44
+ "updated_at" timestamp DEFAULT now() NOT NULL
45
+ );--> statement-breakpoint
46
+
47
+ DO $$ BEGIN
48
+ ALTER TABLE "billing_subscription" ADD CONSTRAINT "billing_subscription_organization_id_organization_id_fk"
49
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
50
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
51
+
52
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_billing_subscription_stripe" ON "billing_subscription" USING btree ("stripe_subscription_id");--> statement-breakpoint
53
+ CREATE INDEX IF NOT EXISTS "idx_billing_subscription_org" ON "billing_subscription" USING btree ("organization_id");--> statement-breakpoint
54
+
55
+ -- ── credit_balance ──────────────────────────────────────────────────────────
56
+ CREATE TABLE IF NOT EXISTS "credit_balance" (
57
+ "organization_id" text PRIMARY KEY NOT NULL,
58
+ "monthly_free_milli" bigint DEFAULT 0 NOT NULL,
59
+ "topup_milli" bigint DEFAULT 0 NOT NULL,
60
+ "updated_at" timestamp DEFAULT now() NOT NULL
61
+ );--> statement-breakpoint
62
+
63
+ DO $$ BEGIN
64
+ ALTER TABLE "credit_balance" ADD CONSTRAINT "credit_balance_organization_id_organization_id_fk"
65
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
66
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
67
+
68
+ -- ── credit_grant ────────────────────────────────────────────────────────────
69
+ CREATE TABLE IF NOT EXISTS "credit_grant" (
70
+ "id" text PRIMARY KEY NOT NULL,
71
+ "organization_id" text NOT NULL,
72
+ "amount_milli" bigint NOT NULL,
73
+ "bucket" text NOT NULL,
74
+ "source" text NOT NULL,
75
+ "source_ref" text,
76
+ "expires_at" timestamp,
77
+ "created_at" timestamp DEFAULT now() NOT NULL
78
+ );--> statement-breakpoint
79
+
80
+ DO $$ BEGIN
81
+ ALTER TABLE "credit_grant" ADD CONSTRAINT "credit_grant_organization_id_organization_id_fk"
82
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
83
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
84
+
85
+ CREATE INDEX IF NOT EXISTS "idx_credit_grant_org_created" ON "credit_grant" USING btree ("organization_id","created_at");--> statement-breakpoint
86
+
87
+ -- ── credit_consumption ──────────────────────────────────────────────────────
88
+ CREATE TABLE IF NOT EXISTS "credit_consumption" (
89
+ "id" text PRIMARY KEY NOT NULL,
90
+ "organization_id" text NOT NULL,
91
+ "oblien_event_id" text NOT NULL,
92
+ "resource_type" text NOT NULL,
93
+ "quantity_milli" bigint NOT NULL,
94
+ "credits_milli" bigint NOT NULL,
95
+ "bucket_consumed" text NOT NULL,
96
+ "occurred_at" timestamp NOT NULL,
97
+ "recorded_at" timestamp DEFAULT now() NOT NULL
98
+ );--> statement-breakpoint
99
+
100
+ DO $$ BEGIN
101
+ ALTER TABLE "credit_consumption" ADD CONSTRAINT "credit_consumption_organization_id_organization_id_fk"
102
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
103
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
104
+
105
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_credit_consumption_org_event" ON "credit_consumption" USING btree ("organization_id","oblien_event_id");--> statement-breakpoint
106
+ CREATE INDEX IF NOT EXISTS "idx_credit_consumption_org_occurred" ON "credit_consumption" USING btree ("organization_id","occurred_at");--> statement-breakpoint
107
+
108
+ -- ── credit_pack ─────────────────────────────────────────────────────────────
109
+ CREATE TABLE IF NOT EXISTS "credit_pack" (
110
+ "id" text PRIMARY KEY NOT NULL,
111
+ "name" text NOT NULL,
112
+ "credits_milli" bigint NOT NULL,
113
+ "price_cents" integer NOT NULL,
114
+ "stripe_product_id" text NOT NULL,
115
+ "stripe_price_id" text NOT NULL,
116
+ "active" boolean DEFAULT true NOT NULL,
117
+ "sort_order" integer DEFAULT 0 NOT NULL
118
+ );--> statement-breakpoint
119
+
120
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_credit_pack_stripe_price" ON "credit_pack" USING btree ("stripe_price_id");--> statement-breakpoint
121
+
122
+ -- ── oblien_usage_cursor ─────────────────────────────────────────────────────
123
+ CREATE TABLE IF NOT EXISTS "oblien_usage_cursor" (
124
+ "organization_id" text PRIMARY KEY NOT NULL,
125
+ "oblien_namespace" text NOT NULL,
126
+ "last_synced_at" timestamp NOT NULL,
127
+ "last_sync_run_at" timestamp NOT NULL,
128
+ "consecutive_failures" integer DEFAULT 0 NOT NULL
129
+ );--> statement-breakpoint
130
+
131
+ DO $$ BEGIN
132
+ ALTER TABLE "oblien_usage_cursor" ADD CONSTRAINT "oblien_usage_cursor_organization_id_organization_id_fk"
133
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
134
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
135
+
136
+ -- ── stripe_webhook_event ────────────────────────────────────────────────────
137
+ CREATE TABLE IF NOT EXISTS "stripe_webhook_event" (
138
+ "stripe_event_id" text PRIMARY KEY NOT NULL,
139
+ "event_type" text NOT NULL,
140
+ "received_at" timestamp DEFAULT now() NOT NULL,
141
+ "processed_at" timestamp
142
+ );
@@ -0,0 +1,14 @@
1
+ -- Partial unique index on credit_grant (organization_id, source, source_ref)
2
+ -- where source_ref IS NOT NULL. Closes the race between the Stripe webhook
3
+ -- and the monthly-reset cron: both used to mint a tier_grant for the same
4
+ -- period boundary, producing two ledger rows + a doubled allowance in the
5
+ -- cache. The unique index makes the second insert a conflict; the writers
6
+ -- use ON CONFLICT DO NOTHING and skip the cache delta when no row landed.
7
+ --
8
+ -- Partial (source_ref IS NOT NULL) so admin/refund grants minted with a
9
+ -- null source_ref are not coerced into uniqueness — those are intentionally
10
+ -- distinct ledger rows.
11
+
12
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_credit_grant_org_source_ref"
13
+ ON "credit_grant" USING btree ("organization_id", "source", "source_ref")
14
+ WHERE "source_ref" IS NOT NULL;
@@ -0,0 +1,23 @@
1
+ -- Demolish the local credit ledger.
2
+ --
3
+ -- Quota is now owned by Oblien (the runtime meters consumption directly and
4
+ -- enforces `setQuota` limits). The local grant/consume/balance triplet and
5
+ -- the Oblien pull-sync cursor are obsolete. The Stripe-side state lives on
6
+ -- in billing_customer / billing_subscription / credit_pack / stripe_webhook_event.
7
+ --
8
+ -- Order matters: drop indexes first (defensive — DROP TABLE drops them too,
9
+ -- but being explicit keeps the diff easy to audit), then the tables in
10
+ -- dependency order. There are no FKs between the four dropped tables, but
11
+ -- credit_consumption + credit_grant + credit_balance + oblien_usage_cursor
12
+ -- all reference organization.id with ON DELETE CASCADE, which postgres
13
+ -- handles cleanly regardless of drop order.
14
+
15
+ DROP INDEX IF EXISTS "uq_credit_grant_org_source_ref";--> statement-breakpoint
16
+ DROP INDEX IF EXISTS "idx_credit_grant_org_created";--> statement-breakpoint
17
+ DROP INDEX IF EXISTS "uq_credit_consumption_org_event";--> statement-breakpoint
18
+ DROP INDEX IF EXISTS "idx_credit_consumption_org_occurred";--> statement-breakpoint
19
+
20
+ DROP TABLE IF EXISTS "credit_consumption";--> statement-breakpoint
21
+ DROP TABLE IF EXISTS "credit_balance";--> statement-breakpoint
22
+ DROP TABLE IF EXISTS "credit_grant";--> statement-breakpoint
23
+ DROP TABLE IF EXISTS "oblien_usage_cursor";
@@ -0,0 +1,81 @@
1
+ -- Smart per-service deploys + git-strategy rollback
2
+ --
3
+ -- Adds the schema surface for two related features:
4
+ --
5
+ -- 1. Smart per-service deploys — record which paths changed between
6
+ -- the previous successful deploy and this one (`changed_paths`),
7
+ -- let the build pipeline skip services whose root_directory was
8
+ -- untouched, and surface the result per-service in the existing
9
+ -- service_deployment table.
10
+ --
11
+ -- 2. Git-strategy rollback — instead of always archiving each
12
+ -- deploy's image + workspace snapshot, projects can opt to roll
13
+ -- back by checking out the prior commit and rebuilding
14
+ -- (`rollback_strategy = "git"`). Cheaper on disk, slower to
15
+ -- restore. Snapshotted per-deployment via `commit_sha_before`.
16
+ --
17
+ -- Idempotent (IF NOT EXISTS guards) so a partial re-apply is safe.
18
+
19
+ -- ── deployment ───────────────────────────────────────────────────────────────
20
+ ALTER TABLE "deployment" ADD COLUMN IF NOT EXISTS "commit_sha_before" text;--> statement-breakpoint
21
+ ALTER TABLE "deployment" ADD COLUMN IF NOT EXISTS "changed_paths" jsonb;--> statement-breakpoint
22
+ ALTER TABLE "deployment" ADD COLUMN IF NOT EXISTS "changed_paths_truncated" boolean DEFAULT false NOT NULL;--> statement-breakpoint
23
+ ALTER TABLE "deployment" ADD COLUMN IF NOT EXISTS "force_all" boolean DEFAULT false NOT NULL;--> statement-breakpoint
24
+ ALTER TABLE "deployment" ADD COLUMN IF NOT EXISTS "rollback_strategy" text DEFAULT 'snapshot' NOT NULL;--> statement-breakpoint
25
+
26
+ -- ── project ──────────────────────────────────────────────────────────────────
27
+ ALTER TABLE "project" ADD COLUMN IF NOT EXISTS "default_rollback_strategy" text DEFAULT 'snapshot' NOT NULL;--> statement-breakpoint
28
+ ALTER TABLE "project" ADD COLUMN IF NOT EXISTS "force_deploy_next" boolean DEFAULT false NOT NULL;--> statement-breakpoint
29
+ ALTER TABLE "project" ADD COLUMN IF NOT EXISTS "monorepo_shared_paths" jsonb;--> statement-breakpoint
30
+ ALTER TABLE "project" ADD COLUMN IF NOT EXISTS "always_rebuild_paths" jsonb;--> statement-breakpoint
31
+
32
+ -- ── service ──────────────────────────────────────────────────────────────────
33
+ ALTER TABLE "service" ADD COLUMN IF NOT EXISTS "always_rebuild_globs" jsonb;--> statement-breakpoint
34
+
35
+ -- ── service_deployment: smart-deploy tracking columns ───────────────────────
36
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "service_name" text;--> statement-breakpoint
37
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "reason" text;--> statement-breakpoint
38
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "reason_skipped" text;--> statement-breakpoint
39
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "url" text;--> statement-breakpoint
40
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "started_at" timestamp;--> statement-breakpoint
41
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "finished_at" timestamp;--> statement-breakpoint
42
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "duration_ms" integer;--> statement-breakpoint
43
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "error_message" text;--> statement-breakpoint
44
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "error" text;--> statement-breakpoint
45
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "check_run_id" bigint;--> statement-breakpoint
46
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "check_run_url" text;--> statement-breakpoint
47
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "artifact_retained_at" timestamp;--> statement-breakpoint
48
+ ALTER TABLE "service_deployment" ADD COLUMN IF NOT EXISTS "logs_ref" text;--> statement-breakpoint
49
+
50
+ -- service_deployment indexes
51
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_service_deployment_dep_svc" ON "service_deployment" USING btree ("deployment_id","service_id");--> statement-breakpoint
52
+ CREATE INDEX IF NOT EXISTS "ix_service_deployment_deployment" ON "service_deployment" USING btree ("deployment_id");--> statement-breakpoint
53
+ CREATE INDEX IF NOT EXISTS "ix_service_deployment_service_status" ON "service_deployment" USING btree ("service_id","status");--> statement-breakpoint
54
+ CREATE INDEX IF NOT EXISTS "ix_service_deployment_service_created" ON "service_deployment" USING btree ("service_id","created_at");--> statement-breakpoint
55
+
56
+ -- ── deployment_check_run ─────────────────────────────────────────────────────
57
+ CREATE TABLE IF NOT EXISTS "deployment_check_run" (
58
+ "id" text PRIMARY KEY NOT NULL,
59
+ "deployment_id" text NOT NULL,
60
+ "check_run_id" bigint NOT NULL,
61
+ "name" text NOT NULL,
62
+ "kind" text NOT NULL,
63
+ "service_deployment_id" text,
64
+ "status" text NOT NULL,
65
+ "conclusion" text,
66
+ "created_at" timestamp DEFAULT now() NOT NULL,
67
+ "updated_at" timestamp DEFAULT now() NOT NULL
68
+ );--> statement-breakpoint
69
+
70
+ DO $$ BEGIN
71
+ ALTER TABLE "deployment_check_run" ADD CONSTRAINT "deployment_check_run_deployment_id_deployment_id_fk"
72
+ FOREIGN KEY ("deployment_id") REFERENCES "public"."deployment"("id") ON DELETE cascade ON UPDATE no action;
73
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
74
+
75
+ DO $$ BEGIN
76
+ ALTER TABLE "deployment_check_run" ADD CONSTRAINT "deployment_check_run_service_deployment_id_service_deployment_id_fk"
77
+ FOREIGN KEY ("service_deployment_id") REFERENCES "public"."service_deployment"("id") ON DELETE cascade ON UPDATE no action;
78
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
79
+
80
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_deployment_check_run_per_kind" ON "deployment_check_run" USING btree ("deployment_id","kind","service_deployment_id");--> statement-breakpoint
81
+ CREATE INDEX IF NOT EXISTS "ix_deployment_check_run_deployment" ON "deployment_check_run" USING btree ("deployment_id");
@@ -0,0 +1,38 @@
1
+ -- ── Fix deployment_check_run uniqueness for rollup rows ─────────────────────
2
+ --
3
+ -- The previous `uq_deployment_check_run_per_kind` index covers
4
+ -- (deployment_id, kind, service_deployment_id). PostgreSQL treats NULLs
5
+ -- as distinct in unique indexes by default, so multiple rows with
6
+ -- (deployment_id, 'rollup', NULL) could coexist — the rollup invariant
7
+ -- of "one rollup row per deployment" was never actually enforced.
8
+ --
9
+ -- This migration replaces that single non-effective index with two
10
+ -- partial unique indexes that match the actual data shapes:
11
+ --
12
+ -- - rollup rows (kind = 'rollup', service_deployment_id IS NULL):
13
+ -- unique on (deployment_id)
14
+ --
15
+ -- - service rows (service_deployment_id IS NOT NULL):
16
+ -- unique on (deployment_id, service_deployment_id)
17
+ --
18
+ -- Also drops a couple of redundant secondary indexes whose lookups are
19
+ -- already covered by the leading column of an existing unique index.
20
+
21
+ DROP INDEX IF EXISTS "uq_deployment_check_run_per_kind";--> statement-breakpoint
22
+
23
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_deployment_check_run_rollup"
24
+ ON "deployment_check_run" ("deployment_id")
25
+ WHERE "kind" = 'rollup';--> statement-breakpoint
26
+
27
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_deployment_check_run_service"
28
+ ON "deployment_check_run" ("deployment_id", "service_deployment_id")
29
+ WHERE "service_deployment_id" IS NOT NULL;--> statement-breakpoint
30
+
31
+ -- Redundant: covered by `uq_deployment_check_run_rollup` /
32
+ -- `uq_deployment_check_run_service` (both have deployment_id as the
33
+ -- leading column), so a separate ix on deployment_id buys nothing.
34
+ DROP INDEX IF EXISTS "ix_deployment_check_run_deployment";--> statement-breakpoint
35
+
36
+ -- Redundant: covered by `uq_service_deployment_dep_svc` whose leading
37
+ -- column is deployment_id.
38
+ DROP INDEX IF EXISTS "ix_service_deployment_deployment";
@@ -0,0 +1,9 @@
1
+ -- Flip the default rollback strategy for NEW projects from "snapshot" to
2
+ -- "git". Existing rows are not touched — they keep whatever they were
3
+ -- created with (a previously-deployed project relying on snapshot
4
+ -- rollback should not silently lose its snapshots).
5
+ --
6
+ -- Users can change the per-project setting via the dashboard's git
7
+ -- settings page.
8
+
9
+ ALTER TABLE "project" ALTER COLUMN "default_rollback_strategy" SET DEFAULT 'git';
@@ -0,0 +1,41 @@
1
+ -- Billing idempotency: per-checkout-session topup grants + per-period
2
+ -- anniversary cron grants. Both protect read-modify-write Oblien quota
3
+ -- mutations from being re-applied when their upstream driver retries:
4
+ -- - stripe_topup_grant Stripe webhook redelivery of checkout.session.completed
5
+ -- would otherwise call addQuota twice → double-credit.
6
+ -- - billing_anniversary_grant Cron crash between Oblien resetQuota and the
7
+ -- local period UPDATE would let the next tick
8
+ -- re-zero quota_used on the new period.
9
+ -- Idempotent (IF NOT EXISTS guards) so applying twice on a partway-through
10
+ -- DB is a no-op.
11
+
12
+ CREATE TABLE IF NOT EXISTS "stripe_topup_grant" (
13
+ "id" text PRIMARY KEY NOT NULL,
14
+ "checkout_session_id" text NOT NULL,
15
+ "organization_id" text NOT NULL,
16
+ "pack_id" text NOT NULL,
17
+ "credits_milli" bigint NOT NULL,
18
+ "granted_at" timestamp DEFAULT now() NOT NULL
19
+ );--> statement-breakpoint
20
+
21
+ DO $$ BEGIN
22
+ ALTER TABLE "stripe_topup_grant" ADD CONSTRAINT "stripe_topup_grant_organization_id_organization_id_fk"
23
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
24
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
25
+
26
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_stripe_topup_grant_session" ON "stripe_topup_grant" USING btree ("checkout_session_id");--> statement-breakpoint
27
+ CREATE INDEX IF NOT EXISTS "idx_stripe_topup_grant_org" ON "stripe_topup_grant" USING btree ("organization_id");--> statement-breakpoint
28
+
29
+ CREATE TABLE IF NOT EXISTS "billing_anniversary_grant" (
30
+ "id" text PRIMARY KEY NOT NULL,
31
+ "organization_id" text NOT NULL,
32
+ "period_start" timestamp NOT NULL,
33
+ "granted_at" timestamp DEFAULT now() NOT NULL
34
+ );--> statement-breakpoint
35
+
36
+ DO $$ BEGIN
37
+ ALTER TABLE "billing_anniversary_grant" ADD CONSTRAINT "billing_anniversary_grant_organization_id_organization_id_fk"
38
+ FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
39
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;--> statement-breakpoint
40
+
41
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_billing_anniversary_grant_org_period" ON "billing_anniversary_grant" USING btree ("organization_id","period_start");
@@ -0,0 +1,30 @@
1
+ -- HIGH-finding fixes for GitHub auth surface (audit, June 2026).
2
+ --
3
+ -- HIGH #6 — github_install_state: short-TTL nonces that bind the install
4
+ -- URL the SaaS hands back to a specific local user/org. Resolves the
5
+ -- "echo-back state with no local binding" hole in the install flow.
6
+ CREATE TABLE "github_install_state" (
7
+ "id" text PRIMARY KEY NOT NULL,
8
+ "state" text NOT NULL,
9
+ "user_id" text NOT NULL,
10
+ "organization_id" text,
11
+ "expires_at" timestamp NOT NULL,
12
+ "created_at" timestamp DEFAULT now() NOT NULL,
13
+ CONSTRAINT "github_install_state_state_unique" UNIQUE("state")
14
+ );
15
+ --> statement-breakpoint
16
+ CREATE INDEX "github_install_state_expires_idx" ON "github_install_state" USING btree ("expires_at");--> statement-breakpoint
17
+ CREATE INDEX "github_install_state_user_idx" ON "github_install_state" USING btree ("user_id");--> statement-breakpoint
18
+
19
+ -- HIGH #9 — per-project webhook signing secret (encrypted via lib/encryption).
20
+ -- Null on legacy rows; verifier falls back to env.GITHUB_WEBHOOK_SECRET there.
21
+ ALTER TABLE "project" ADD COLUMN "webhook_secret" text;--> statement-breakpoint
22
+
23
+ -- HIGH #7 — explicit operator opt-in for the gh CLI escape hatch.
24
+ -- Without this, "owner of any org" gated transitive access to the
25
+ -- operator's broad-scope PAT.
26
+ ALTER TABLE "user_settings" ADD COLUMN "gh_cli_operator_opted_in" boolean DEFAULT false NOT NULL;--> statement-breakpoint
27
+
28
+ -- HIGH #10 — PAT scope cached from inspectPatScope so we can re-validate
29
+ -- at use time without re-issuing `GET /user`.
30
+ ALTER TABLE "user_settings" ADD COLUMN "pat_scope" jsonb;
@@ -0,0 +1,6 @@
1
+ CREATE TABLE "oblien_webhook_event" (
2
+ "oblien_event_id" text PRIMARY KEY NOT NULL,
3
+ "event_type" text NOT NULL,
4
+ "received_at" timestamp DEFAULT now() NOT NULL,
5
+ "processed_at" timestamp
6
+ );
@@ -0,0 +1 @@
1
+ ALTER TABLE "project" ADD COLUMN "deletion_in_progress" boolean DEFAULT false NOT NULL;
@@ -0,0 +1 @@
1
+ ALTER TABLE "project" RENAME COLUMN "workspace_install_command" TO "workspace_prepare_command";
@@ -0,0 +1,13 @@
1
+ CREATE TABLE "server_tunnels" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "server_id" text NOT NULL,
4
+ "remote_port" integer NOT NULL,
5
+ "remote_host" text DEFAULT '127.0.0.1' NOT NULL,
6
+ "local_port" integer,
7
+ "auto_start" boolean DEFAULT false NOT NULL,
8
+ "created_at" timestamp DEFAULT now() NOT NULL,
9
+ "updated_at" timestamp DEFAULT now() NOT NULL
10
+ );
11
+ --> statement-breakpoint
12
+ ALTER TABLE "server_tunnels" ADD CONSTRAINT "server_tunnels_server_id_servers_id_fk" FOREIGN KEY ("server_id") REFERENCES "public"."servers"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
13
+ CREATE UNIQUE INDEX "uq_server_tunnel_target" ON "server_tunnels" USING btree ("server_id","remote_port","remote_host");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "deployment" ADD COLUMN "version" integer;--> statement-breakpoint
2
+ ALTER TABLE "project" ADD COLUMN "runtime_mode" text;
@@ -0,0 +1,6 @@
1
+ -- Versions now represent shipped releases: a deployment gets its version number
2
+ -- in onSuccess (per-commit), not at create. Clear the per-attempt numbers that
3
+ -- the old MAX(version)+1-at-create logic assigned to non-successful deploys so
4
+ -- failed/in-flight rows stop showing a stale vN badge. Successful (ready) rows
5
+ -- keep their existing numbers.
6
+ UPDATE "deployment" SET "version" = NULL WHERE "status" <> 'ready';
@@ -0,0 +1,17 @@
1
+ CREATE TABLE "personal_access_token" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "user_id" text NOT NULL,
4
+ "organization_id" text,
5
+ "name" text NOT NULL,
6
+ "token_prefix" text NOT NULL,
7
+ "token_hash" text NOT NULL,
8
+ "read_only" boolean DEFAULT false NOT NULL,
9
+ "expires_at" timestamp,
10
+ "last_used_at" timestamp,
11
+ "revoked_at" timestamp,
12
+ "created_at" timestamp DEFAULT now() NOT NULL,
13
+ CONSTRAINT "personal_access_token_token_hash_unique" UNIQUE("token_hash")
14
+ );
15
+ --> statement-breakpoint
16
+ CREATE INDEX "personal_access_token_user_idx" ON "personal_access_token" USING btree ("user_id");--> statement-breakpoint
17
+ CREATE INDEX "personal_access_token_prefix_idx" ON "personal_access_token" USING btree ("token_prefix");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "service" ADD COLUMN "imported_spec" jsonb;--> statement-breakpoint
2
+ ALTER TABLE "service" ADD COLUMN "drift_spec" jsonb;
@@ -0,0 +1 @@
1
+ ALTER TABLE "service" ADD COLUMN "advanced" jsonb DEFAULT '{}'::jsonb;
@@ -0,0 +1,11 @@
1
+ ALTER TABLE "backup_policy" ALTER COLUMN "project_id" DROP NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "backup_policy" ADD COLUMN "source_kind" text DEFAULT 'service' NOT NULL;--> statement-breakpoint
3
+ ALTER TABLE "backup_policy" ADD COLUMN "mail_server_id" text;--> statement-breakpoint
4
+ ALTER TABLE "backup_restore" ADD COLUMN "fork_mail_server_id" text;--> statement-breakpoint
5
+ ALTER TABLE "backup_run" ADD COLUMN "source_kind" text DEFAULT 'service' NOT NULL;--> statement-breakpoint
6
+ ALTER TABLE "backup_run" ADD COLUMN "mail_server_id" text;--> statement-breakpoint
7
+ ALTER TABLE "backup_policy" ADD CONSTRAINT "backup_policy_mail_server_id_mail_servers_server_id_fk" FOREIGN KEY ("mail_server_id") REFERENCES "public"."mail_servers"("server_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
8
+ ALTER TABLE "backup_restore" ADD CONSTRAINT "backup_restore_fork_mail_server_id_mail_servers_server_id_fk" FOREIGN KEY ("fork_mail_server_id") REFERENCES "public"."mail_servers"("server_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
9
+ ALTER TABLE "backup_run" ADD CONSTRAINT "backup_run_mail_server_id_mail_servers_server_id_fk" FOREIGN KEY ("mail_server_id") REFERENCES "public"."mail_servers"("server_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
10
+ CREATE UNIQUE INDEX "uq_backup_policy_mail_server" ON "backup_policy" USING btree ("mail_server_id") WHERE "backup_policy"."mail_server_id" IS NOT NULL AND "backup_policy"."deleted_at" IS NULL;--> statement-breakpoint
11
+ CREATE INDEX "idx_backup_policy_mail_server" ON "backup_policy" USING btree ("mail_server_id");
@@ -0,0 +1,6 @@
1
+ ALTER TABLE "service" ADD COLUMN "namespace_volumes" boolean DEFAULT true NOT NULL;--> statement-breakpoint
2
+ -- Grandfather every EXISTING service to bare (un-scoped) volume names so their
3
+ -- on-disk data is not orphaned. Rows created AFTER this migration take the
4
+ -- column default (true) and get project-scoped volumes. Load-bearing: without
5
+ -- it, ADD COLUMN DEFAULT true would scope existing services and lose their data.
6
+ UPDATE "service" SET "namespace_volumes" = false;
@@ -0,0 +1,18 @@
1
+ CREATE TABLE "orphaned_resource" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "organization_id" text NOT NULL,
4
+ "server_id" text,
5
+ "resource_type" text NOT NULL,
6
+ "ref" text NOT NULL,
7
+ "project_id" text,
8
+ "label" text,
9
+ "runtime_mode" text,
10
+ "payload" jsonb,
11
+ "attempts" integer DEFAULT 0 NOT NULL,
12
+ "last_attempt_at" timestamp,
13
+ "created_at" timestamp DEFAULT now() NOT NULL
14
+ );
15
+ --> statement-breakpoint
16
+ ALTER TABLE "orphaned_resource" ADD CONSTRAINT "orphaned_resource_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
17
+ CREATE INDEX "orphaned_resource_server_idx" ON "orphaned_resource" USING btree ("server_id");--> statement-breakpoint
18
+ CREATE INDEX "orphaned_resource_org_created_idx" ON "orphaned_resource" USING btree ("organization_id","created_at");
@@ -0,0 +1,16 @@
1
+ CREATE TABLE "cloud_webhook_binding" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "organization_id" text NOT NULL,
4
+ "cloud_project_id" text NOT NULL,
5
+ "git_owner" text NOT NULL,
6
+ "git_repo" text NOT NULL,
7
+ "git_branch" text DEFAULT '' NOT NULL,
8
+ "webhook_id" integer,
9
+ "webhook_secret" text,
10
+ "created_at" timestamp DEFAULT now() NOT NULL,
11
+ "updated_at" timestamp DEFAULT now() NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ ALTER TABLE "cloud_webhook_binding" ADD CONSTRAINT "cloud_webhook_binding_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
15
+ CREATE UNIQUE INDEX "uq_cloud_webhook_binding_repo_branch" ON "cloud_webhook_binding" USING btree ("git_owner","git_repo","git_branch");--> statement-breakpoint
16
+ CREATE INDEX "idx_cloud_webhook_binding_cloud_project" ON "cloud_webhook_binding" USING btree ("cloud_project_id");
@@ -0,0 +1,6 @@
1
+ CREATE TABLE "github_webhook_event" (
2
+ "delivery_id" text PRIMARY KEY NOT NULL,
3
+ "event_type" text NOT NULL,
4
+ "received_at" timestamp DEFAULT now() NOT NULL,
5
+ "processed_at" timestamp
6
+ );