@rebasepro/server-postgres 0.17.3 → 0.18.1

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 (204) hide show
  1. package/LICENSE +0 -1
  2. package/README.md +31 -0
  3. package/dist/BranchService-ByLfM_Tt.js +360 -0
  4. package/dist/BranchService-ByLfM_Tt.js.map +1 -0
  5. package/dist/__vite-browser-external-BnuHet1e.js +46 -0
  6. package/dist/__vite-browser-external-BnuHet1e.js.map +1 -0
  7. package/dist/arg-Dni7MzLB.js +87 -0
  8. package/dist/arg-Dni7MzLB.js.map +1 -0
  9. package/dist/auth-users-columns-D2LBFrMH.js +116 -0
  10. package/dist/auth-users-columns-D2LBFrMH.js.map +1 -0
  11. package/dist/backup-argv.d.ts +19 -0
  12. package/dist/backup-cli-oM9WQVlV.js +408 -0
  13. package/dist/backup-cli-oM9WQVlV.js.map +1 -0
  14. package/dist/backup-service-Br3tqwsy.js +715 -0
  15. package/dist/backup-service-Br3tqwsy.js.map +1 -0
  16. package/dist/branch-argv.d.ts +28 -0
  17. package/dist/branch-prune.d.ts +77 -0
  18. package/dist/cli-collections-path.d.ts +31 -0
  19. package/dist/cli-errors-DxN4yzdH.js +657 -0
  20. package/dist/cli-errors-DxN4yzdH.js.map +1 -0
  21. package/dist/cli-errors.d.ts +123 -0
  22. package/dist/cli-flags.d.ts +101 -0
  23. package/dist/cli-helpers.d.ts +94 -10
  24. package/dist/cli-output-CNdMql-L.js +47 -0
  25. package/dist/cli-output-CNdMql-L.js.map +1 -0
  26. package/dist/cli.js +2020 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/collection-index-BHgT_TKd.js +276 -0
  29. package/dist/collection-index-BHgT_TKd.js.map +1 -0
  30. package/dist/{collections-schema-version-BMeu3cgv.js → collections-schema-version-T6cGvrDi.js} +1 -2
  31. package/dist/{collections-schema-version-BMeu3cgv.js.map → collections-schema-version-T6cGvrDi.js.map} +1 -1
  32. package/dist/{connection-GOKU3Hu5.js → databasePoolManager-Bj5FbeAs.js} +112 -40
  33. package/dist/databasePoolManager-Bj5FbeAs.js.map +1 -0
  34. package/dist/databasePoolManager.d.ts +27 -0
  35. package/dist/doctor-D7HWmGzs.js +974 -0
  36. package/dist/doctor-D7HWmGzs.js.map +1 -0
  37. package/dist/{ensure-collection-policies-UCqgv_8c.js → ensure-collection-policies-2c2NV8zX.js} +7 -27
  38. package/dist/ensure-collection-policies-2c2NV8zX.js.map +1 -0
  39. package/dist/ensure-collection-tables-D4wJzM4y.js +820 -0
  40. package/dist/ensure-collection-tables-D4wJzM4y.js.map +1 -0
  41. package/dist/ensure-tables-CIojK-Rx.js +650 -0
  42. package/dist/ensure-tables-CIojK-Rx.js.map +1 -0
  43. package/dist/generate-drizzle-schema-CwEgVyjO.js +123 -0
  44. package/dist/generate-drizzle-schema-CwEgVyjO.js.map +1 -0
  45. package/dist/generate-drizzle-schema-logic-so2Z_lyC.js +528 -0
  46. package/dist/generate-drizzle-schema-logic-so2Z_lyC.js.map +1 -0
  47. package/dist/{ensure-collection-tables-DgVixhX3.js → generate-postgres-ddl-logic-CtnpIBVv.js} +126 -984
  48. package/dist/generate-postgres-ddl-logic-CtnpIBVv.js.map +1 -0
  49. package/dist/generated-schema-staleness-DQdfJl2A.js +157 -0
  50. package/dist/generated-schema-staleness-DQdfJl2A.js.map +1 -0
  51. package/dist/index.d.ts +12 -0
  52. package/dist/index.es.js +7423 -1133
  53. package/dist/index.es.js.map +1 -1
  54. package/dist/introspect-db-logic-C6LQdTxj.js +1378 -0
  55. package/dist/introspect-db-logic-C6LQdTxj.js.map +1 -0
  56. package/dist/policy-drift-kNJ6X2Uj.js +313 -0
  57. package/dist/policy-drift-kNJ6X2Uj.js.map +1 -0
  58. package/dist/{backup-service-DCk7KhhL.js → rls-bootstrap-sql-DLDnUjtx.js} +737 -2689
  59. package/dist/rls-bootstrap-sql-DLDnUjtx.js.map +1 -0
  60. package/dist/{rls-enforcement-DvAbL9YJ.js → rls-enforcement-DeYEjYLt.js} +65 -190
  61. package/dist/rls-enforcement-DeYEjYLt.js.map +1 -0
  62. package/dist/schema/bin/generate-drizzle-schema.d.ts +1 -0
  63. package/dist/schema/bin/generate-postgres-ddl.d.ts +1 -0
  64. package/dist/schema/column-type-drift.d.ts +79 -0
  65. package/dist/schema/doctor-cli.js +129 -0
  66. package/dist/schema/doctor-cli.js.map +1 -0
  67. package/dist/schema/doctor.d.ts +42 -0
  68. package/dist/schema/ensure-collection-tables.d.ts +90 -0
  69. package/dist/schema/generate-drizzle-schema.d.ts +1 -1
  70. package/dist/schema/generate-drizzle-schema.js +24 -0
  71. package/dist/schema/generate-drizzle-schema.js.map +1 -0
  72. package/dist/schema/generate-next-step.d.ts +30 -0
  73. package/dist/schema/generate-postgres-ddl-logic.d.ts +28 -0
  74. package/dist/schema/generate-postgres-ddl.d.ts +1 -1
  75. package/dist/schema/generate-postgres-ddl.js +138 -0
  76. package/dist/schema/generate-postgres-ddl.js.map +1 -0
  77. package/dist/schema/generated-schema-staleness.d.ts +37 -0
  78. package/dist/schema/introspect-db-queries.d.ts +34 -0
  79. package/dist/schema/introspect-db.js +866 -0
  80. package/dist/schema/introspect-db.js.map +1 -0
  81. package/dist/security/rls-enforcement.d.ts +63 -2
  82. package/dist/services/BranchService.d.ts +86 -1
  83. package/dist/services/collection-helpers.d.ts +1 -1
  84. package/dist/services/realtimeService.d.ts +30 -2
  85. package/dist/services/row-pipeline.d.ts +12 -1
  86. package/dist/source-Br7L7GOI.js +410 -0
  87. package/dist/source-Br7L7GOI.js.map +1 -0
  88. package/dist/utils/pg-error-utils.d.ts +3 -1
  89. package/dist/utils/pg-numeric-number-patch.d.ts +31 -0
  90. package/dist/vector-index-DkWxm2de.js +309 -0
  91. package/dist/vector-index-DkWxm2de.js.map +1 -0
  92. package/package.json +32 -27
  93. package/dist/backup-service-DCk7KhhL.js.map +0 -1
  94. package/dist/collection-index-BRUg10H5.js +0 -5690
  95. package/dist/collection-index-BRUg10H5.js.map +0 -1
  96. package/dist/connection-GOKU3Hu5.js.map +0 -1
  97. package/dist/ensure-collection-policies-UCqgv_8c.js.map +0 -1
  98. package/dist/ensure-collection-tables-DgVixhX3.js.map +0 -1
  99. package/dist/rls-bootstrap-sql-B5C9LoJ6.js +0 -244
  100. package/dist/rls-bootstrap-sql-B5C9LoJ6.js.map +0 -1
  101. package/dist/rls-enforcement-DvAbL9YJ.js.map +0 -1
  102. package/dist/src-DiB5RP2Z.js +0 -541
  103. package/dist/src-DiB5RP2Z.js.map +0 -1
  104. package/dist/websocket-BZ4H5wUz.js +0 -8198
  105. package/dist/websocket-BZ4H5wUz.js.map +0 -1
  106. package/src/PostgresAdapter.ts +0 -91
  107. package/src/PostgresBackendDriver.ts +0 -1857
  108. package/src/PostgresBootstrapper.ts +0 -1157
  109. package/src/auth/ensure-tables.ts +0 -896
  110. package/src/auth/schema-version.ts +0 -260
  111. package/src/auth/services.ts +0 -1610
  112. package/src/backup/backup-cli.ts +0 -520
  113. package/src/backup/backup-cron.ts +0 -212
  114. package/src/backup/backup-logic.ts +0 -93
  115. package/src/backup/backup-service.ts +0 -485
  116. package/src/backup/index.ts +0 -12
  117. package/src/backup/pg-tools.ts +0 -403
  118. package/src/backup/retention.ts +0 -86
  119. package/src/cli-errors.ts +0 -265
  120. package/src/cli-helpers.ts +0 -569
  121. package/src/cli-output.ts +0 -43
  122. package/src/cli.ts +0 -1339
  123. package/src/collections/PostgresCollectionRegistry.ts +0 -108
  124. package/src/collections/buildRegistry.ts +0 -68
  125. package/src/collections/validate-relations.ts +0 -402
  126. package/src/connection.ts +0 -333
  127. package/src/data-transformer.ts +0 -845
  128. package/src/databasePoolManager.ts +0 -95
  129. package/src/history/HistoryService.ts +0 -254
  130. package/src/history/ensure-history-table.ts +0 -53
  131. package/src/index.ts +0 -19
  132. package/src/interfaces.ts +0 -60
  133. package/src/module-dir.ts +0 -7
  134. package/src/schema/atlas-argv.ts +0 -94
  135. package/src/schema/auth-schema.ts +0 -298
  136. package/src/schema/auth-users-columns.ts +0 -131
  137. package/src/schema/carved-out-migration.ts +0 -404
  138. package/src/schema/classify-change.ts +0 -436
  139. package/src/schema/collection-index.ts +0 -427
  140. package/src/schema/collections-schema-version.ts +0 -103
  141. package/src/schema/destructive-sql.ts +0 -94
  142. package/src/schema/doctor-cli.ts +0 -66
  143. package/src/schema/doctor-policy-checks.ts +0 -105
  144. package/src/schema/doctor.ts +0 -837
  145. package/src/schema/drizzle-ddl.ts +0 -33
  146. package/src/schema/dynamic-tables.test.ts +0 -302
  147. package/src/schema/dynamic-tables.ts +0 -293
  148. package/src/schema/ensure-collection-policies.ts +0 -198
  149. package/src/schema/ensure-collection-tables.test.ts +0 -518
  150. package/src/schema/ensure-collection-tables.ts +0 -1267
  151. package/src/schema/generate-drizzle-schema-logic.ts +0 -957
  152. package/src/schema/generate-drizzle-schema.ts +0 -143
  153. package/src/schema/generate-postgres-ddl-logic.ts +0 -1339
  154. package/src/schema/generate-postgres-ddl.ts +0 -180
  155. package/src/schema/generate-schema-commit.ts +0 -267
  156. package/src/schema/generated-schema-staleness.ts +0 -284
  157. package/src/schema/introspect-db-constraints.ts +0 -385
  158. package/src/schema/introspect-db-inference.ts +0 -255
  159. package/src/schema/introspect-db-logic.ts +0 -1387
  160. package/src/schema/introspect-db-naming.ts +0 -15
  161. package/src/schema/introspect-db-project.ts +0 -78
  162. package/src/schema/introspect-db-queries.ts +0 -326
  163. package/src/schema/introspect-db-structure.ts +0 -670
  164. package/src/schema/introspect-db-types.ts +0 -56
  165. package/src/schema/introspect-db.ts +0 -257
  166. package/src/schema/introspect-runtime.test.ts +0 -260
  167. package/src/schema/introspect-runtime.ts +0 -327
  168. package/src/schema/non-sql-collections.test.ts +0 -131
  169. package/src/schema/rls-bootstrap-sql.ts +0 -288
  170. package/src/schema/search-column.ts +0 -643
  171. package/src/schema/test-schema.ts +0 -11
  172. package/src/schema/vector-index.ts +0 -491
  173. package/src/security/anonymous-grants.test.ts +0 -73
  174. package/src/security/policy-drift.test.ts +0 -435
  175. package/src/security/policy-drift.ts +0 -473
  176. package/src/security/rls-enforcement.ts +0 -505
  177. package/src/services/BranchService.ts +0 -326
  178. package/src/services/FetchService.ts +0 -2115
  179. package/src/services/PersistService.ts +0 -557
  180. package/src/services/RelationService.ts +0 -978
  181. package/src/services/RelationWriteService.ts +0 -653
  182. package/src/services/cdc/CdcListener.ts +0 -103
  183. package/src/services/cdc/junction-tables.ts +0 -91
  184. package/src/services/cdc/trigger-cdc.ts +0 -173
  185. package/src/services/channel-bus/ChannelBus.ts +0 -44
  186. package/src/services/channel-bus/PostgresChannelBus.ts +0 -299
  187. package/src/services/channel-bus/index.ts +0 -114
  188. package/src/services/channel-history.ts +0 -424
  189. package/src/services/channel-presence.ts +0 -185
  190. package/src/services/collection-helpers.ts +0 -420
  191. package/src/services/dataService.ts +0 -256
  192. package/src/services/index.ts +0 -14
  193. package/src/services/junction-writes.ts +0 -295
  194. package/src/services/nested-path.ts +0 -145
  195. package/src/services/pg-notify-listener.ts +0 -151
  196. package/src/services/realtimeService.ts +0 -2545
  197. package/src/services/row-pipeline.ts +0 -240
  198. package/src/services/write-denial.ts +0 -55
  199. package/src/types.ts +0 -4
  200. package/src/utils/connection-string.ts +0 -58
  201. package/src/utils/drizzle-conditions.ts +0 -2743
  202. package/src/utils/pg-array-null-patch.ts +0 -42
  203. package/src/utils/pg-error-utils.ts +0 -391
  204. package/src/websocket.ts +0 -855
@@ -1,198 +0,0 @@
1
- /**
2
- * Applying a bundle's RLS policies to a database at boot, idempotently.
3
- *
4
- * ## Why this exists
5
- *
6
- * {@link ensureCollectionTables} creates the collection *tables* a managed
7
- * runtime boots against, but a table with row-level security disabled and no
8
- * policies is not servable: authenticated requests run as the restricted
9
- * `rebase_user` role, so a read with no `SELECT` policy returns nothing (a
10
- * public collection answered 401) and a write with no `INSERT`/`UPDATE` policy
11
- * is denied. The policies live in the collections' `securityRules`; nothing at
12
- * boot applied them. `rebase db push` does — but it drives Atlas against a
13
- * local `DATABASE_URL`, and a managed tenant's database is reachable only from
14
- * inside the cluster, by the runtime that is already connected to it. So the
15
- * runtime is the only thing that *can* apply them, and this is where it does.
16
- *
17
- * ## Why this is safe to run on every boot
18
- *
19
- * Every statement is idempotent: `ENABLE ROW LEVEL SECURITY` is a no-op once
20
- * enabled, and each policy is a `DROP POLICY IF EXISTS` immediately followed by
21
- * a `CREATE POLICY`, so re-applying asserts exactly the declared state. It adds
22
- * and replaces; it never drops data. (It does not *reconcile* — a policy a
23
- * previous push left behind under an old name is not removed here; that stays a
24
- * `db push` / `db migrate` concern, alongside destructive schema changes.)
25
- *
26
- * Unlike table creation, a failure here is not fatal: RLS stays enabled, so a
27
- * table whose policies could not be applied fails **closed** (denies) rather
28
- * than leaking rows. One collection's policy failing (e.g. a rule that
29
- * references a table a real migration has not created yet) must not crash-loop
30
- * the whole deployment and take the other collections' working routes down with
31
- * it. Failures are reported loudly and per-table so the operator can see
32
- * exactly which collection is not yet servable and why.
33
- */
34
- import { type CollectionConfig } from "@rebasepro/types";
35
- import { planCollectionPolicies, type CollectionPolicyPlan } from "./generate-postgres-ddl-logic";
36
- import { isGeneratedPolicyName } from "../security/policy-drift";
37
- import { readExistingSchema, type Queryable } from "./ensure-collection-tables";
38
- import { REBASE_USER_ROLE } from "../security/rls-enforcement";
39
-
40
- export interface PolicyEnsureResult {
41
- /** `CREATE POLICY` statements that ran successfully. */
42
- policiesApplied: number;
43
- /** Tables that had RLS enabled. */
44
- tablesSecured: number;
45
- /** Declared tables absent from the database — left to a real migration. */
46
- skipped: { table: string; reason: string }[];
47
- /**
48
- * Tables that have RLS on but did not get every policy. They deny — RLS
49
- * with no matching policy is deny-all — so they are safe but not servable.
50
- */
51
- failures: { table: string; error: string }[];
52
- /**
53
- * Tables RLS could not be enabled on, whose DML grant was withdrawn instead.
54
- *
55
- * This state had no name, and that was the bug: `ENABLE ROW LEVEL SECURITY`
56
- * failing was recorded as a `failure` and reported with the same "it stays
57
- * locked (denies)" wording as a failed policy — but the two are opposites.
58
- * A policy statement failing leaves RLS on and the table denying. `enableRls`
59
- * failing leaves RLS *off*, and the schema-wide grant to the user role has
60
- * already been made by `ensureRlsEnforcement`, so the table is readable and
61
- * writable by every authenticated request with no row filtering at all.
62
- */
63
- unsecured: { table: string; error: string; grantWithdrawn: boolean }[];
64
- /**
65
- * Generated policies removed because no current rule produces them.
66
- *
67
- * A policy's name embeds a hash of the rule's semantics, so editing a rule
68
- * does not update a policy — it creates a new one and abandons the old.
69
- * Postgres ORs permissive policies, so the abandoned one keeps granting:
70
- * a `USING (true)` tightened to an owner check went on admitting everyone,
71
- * forever, while the deploy logged success.
72
- *
73
- * `db push` reconciles this, and cannot reach a managed tenant's in-cluster
74
- * database — which is the reason this module exists. So boot has to do it.
75
- */
76
- orphansDropped: number;
77
- }
78
-
79
- const isCreatePolicy = (statement: string): boolean => /^\s*CREATE POLICY/i.test(statement);
80
-
81
- /**
82
- * Bring the declared collections' RLS policies up to date. Returns what it did.
83
- *
84
- * Only tables that already exist are touched: the boot-time table creator runs
85
- * first, so anything still missing is a table this additive path is not allowed
86
- * to create (a junction, or a relation left to a migration). Enabling RLS on a
87
- * non-existent table would error, so those are recorded as skipped, not failed.
88
- */
89
-
90
- /**
91
- * Remove generated policies on this table that the current plan does not
92
- * produce.
93
- *
94
- * Scoped hard, because dropping a policy is destructive: only this one table,
95
- * only names matching the generated `<table>_<op>_<sha1>` shape, and only names
96
- * absent from the statements just applied. A hand-written policy, or one
97
- * belonging to another table, is never touched — `isGeneratedPolicyName` is the
98
- * same predicate `db push` uses to draw that line.
99
- */
100
- async function dropOrphanedPoliciesOn(client: Queryable, plan: CollectionPolicyPlan): Promise<number> {
101
- const expected = new Set<string>();
102
- for (const statement of plan.policyStatements) {
103
- const match = /^\s*CREATE POLICY\s+"([^"]+)"/i.exec(statement);
104
- if (match) expected.add(match[1]);
105
- }
106
-
107
- const existing = await client.query<{ policyname: string }>(
108
- `SELECT policyname FROM pg_policies WHERE schemaname = '${plan.schema.replace(/'/g, "''")}' ` +
109
- `AND tablename = '${plan.table.replace(/'/g, "''")}'`
110
- );
111
-
112
- let dropped = 0;
113
- for (const row of existing.rows) {
114
- const name = row.policyname;
115
- if (expected.has(name)) continue;
116
- if (!isGeneratedPolicyName(name, plan.table)) continue;
117
- await client.query(`DROP POLICY IF EXISTS "${name}" ON "${plan.schema}"."${plan.table}"`);
118
- dropped++;
119
- }
120
- return dropped;
121
- }
122
-
123
- export async function ensureCollectionPolicies(
124
- client: Queryable,
125
- collections: CollectionConfig[],
126
- log?: (message: string) => void
127
- ): Promise<PolicyEnsureResult> {
128
- const result: PolicyEnsureResult = { policiesApplied: 0, tablesSecured: 0, skipped: [], failures: [], unsecured: [], orphansDropped: 0 };
129
-
130
- const plans = planCollectionPolicies(collections);
131
- if (plans.length === 0) return result;
132
-
133
- const schemas = Array.from(new Set(plans.map(p => p.schema)));
134
- const existing = await readExistingSchema(client, schemas);
135
-
136
- for (const plan of plans) {
137
- if (!existing.tables.has(plan.qualified)) {
138
- result.skipped.push({
139
- table: plan.qualified,
140
- reason: "table is not present in the database; create it with `rebase db push` / `rebase db migrate`"
141
- });
142
- continue;
143
- }
144
-
145
- // Enabling RLS is its own step, because its failure is the opposite of
146
- // every other failure here. Once RLS is on, anything that goes wrong
147
- // afterwards leaves the table denying; while it is off, the grant made
148
- // earlier in boot leaves the table wide open. Sharing one `try` meant
149
- // the dangerous case was reported in the safe case's words.
150
- try {
151
- await client.query(plan.enableRls);
152
- result.tablesSecured++;
153
- } catch (err) {
154
- const error = err instanceof Error ? err.message : String(err);
155
- // Take the privilege back rather than serve an unprotected table.
156
- // This is the fail-closed step the old code assumed it already had:
157
- // per-table, so one collection cannot take the rest of the
158
- // deployment down, but leaving nothing readable without RLS.
159
- let grantWithdrawn = false;
160
- try {
161
- await client.query(`REVOKE ALL PRIVILEGES ON ${plan.qualified} FROM ${REBASE_USER_ROLE}`);
162
- grantWithdrawn = true;
163
- } catch {
164
- // Fall through: reported below with `grantWithdrawn: false`,
165
- // which the caller escalates. There is nothing else this
166
- // function can do to make the table safe.
167
- }
168
- result.unsecured.push({ table: plan.qualified,
169
- error,
170
- grantWithdrawn });
171
- continue;
172
- }
173
-
174
- try {
175
- let created = 0;
176
- for (const statement of plan.policyStatements) {
177
- await client.query(statement);
178
- if (isCreatePolicy(statement)) {
179
- result.policiesApplied++;
180
- created++;
181
- }
182
- }
183
-
184
- const orphans = await dropOrphanedPoliciesOn(client, plan);
185
- result.orphansDropped += orphans;
186
-
187
- log?.(`${plan.qualified}: RLS enabled, ${created} policy(ies) applied` +
188
- (orphans > 0 ? `, ${orphans} orphan(s) dropped` : ""));
189
- } catch (err) {
190
- result.failures.push({
191
- table: plan.qualified,
192
- error: err instanceof Error ? err.message : String(err)
193
- });
194
- }
195
- }
196
-
197
- return result;
198
- }