@rebasepro/common 0.17.1-canary.ga1d9dad → 0.17.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.
package/dist/index.es.js CHANGED
@@ -2837,7 +2837,10 @@ var REBASE_USER_ROLE = "rebase_user";
2837
2837
  *
2838
2838
  * Deliberately NOT including `users`: the auth user table is also a collection,
2839
2839
  * with `securityRules`, RLS enabled and policies applied. Users read their own
2840
- * row through it — revoking there would break sign-in.
2840
+ * row through it — revoking there would break sign-in. `revokeInternalTableSql`
2841
+ * now skips any table with RLS enabled, so that exception is enforced rather
2842
+ * than merely remembered — and so is the same hazard for every other name here,
2843
+ * any of which a project may legitimately use for a collection of its own.
2841
2844
  *
2842
2845
  * `atlas_schema_revisions` is Atlas's migration ledger, which lands in `rebase`
2843
2846
  * because `db migrate apply` passes `--revisions-schema rebase`.
@@ -2848,8 +2851,16 @@ var REBASE_USER_ROLE = "rebase_user";
2848
2851
  * list is what the boot-time sweep in `ensureAppRole` iterates, and the sweep
2849
2852
  * is the only thing that can repair an already-granted table. A table revoked
2850
2853
  * at creation but missing here is therefore permanently stranded on any
2851
- * database that predates its revoke — which is exactly what happened to
2852
- * `jobs`, added here after a scan of a pre-0.14 database found it.
2854
+ * database that predates its revoke.
2855
+ *
2856
+ * These names are unqualified, and the boot-time sweep applies them to every
2857
+ * schema a project uses — so an entry here is a claim on that name in `public`
2858
+ * as much as in `rebase`. `jobs` is Rebase's queue at `rebase.jobs` AND a
2859
+ * perfectly ordinary collection name, and revoking `public.jobs` from a project
2860
+ * that owns it leaves every read failing 42501 with correct policies applied
2861
+ * and nothing in the RLS logs to explain it. The `relrowsecurity` guard in
2862
+ * `revokeInternalTableSql` is what makes a common noun safe here — it is not a
2863
+ * licence to claim more of them.
2853
2864
  */
2854
2865
  var REBASE_INTERNAL_TABLES = [
2855
2866
  "user_identities",
@@ -2890,6 +2901,25 @@ var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_$]*$/;
2890
2901
  * - the table may not exist yet — `cron_logs` never appears in a project with
2891
2902
  * no cron jobs — and `to_regclass` returning NULL has to be tolerated too.
2892
2903
  *
2904
+ * The third guard is the one that decides whether the *right* table is being
2905
+ * revoked. The names in {@link REBASE_INTERNAL_TABLES} are unqualified, and the
2906
+ * boot-time sweep in `ensureAppRole` applies all of them to every schema a
2907
+ * project uses — including the schema its own collections live in. A project is
2908
+ * free to call a collection `jobs`, `branches` or `api_keys`, and when it does,
2909
+ * the sweep was revoking `rebase_user`'s DML on the project's table on every
2910
+ * single boot. That is not a subtle degradation: the collection's whole API
2911
+ * answers 500 `permission denied for table …` from then on, which is what
2912
+ * happened to a public job board whose vacancies live in `public.jobs`.
2913
+ *
2914
+ * `relrowsecurity` separates the two cleanly, and it is the same fact this
2915
+ * module already relies on. Framework-internal tables carry no RLS — that is the
2916
+ * premise stated at the top of this file, and the reason a revoke is needed at
2917
+ * all. Every collection table has it enabled, because that is how Rebase
2918
+ * enforces `securityRules`. So "RLS is off" is exactly "this is not somebody's
2919
+ * collection", and the guard also subsumes the hand-carved `users` exception:
2920
+ * the auth user table is a collection, has RLS, and would now be skipped on its
2921
+ * own merits rather than by being kept off a list.
2922
+ *
2893
2923
  * One command, so it is safe on handles that speak the extended query protocol
2894
2924
  * and reject multi-statement strings.
2895
2925
  */
@@ -2901,7 +2931,8 @@ function revokeInternalTableSql(schema, table) {
2901
2931
  DO $rebase_revoke$
2902
2932
  BEGIN
2903
2933
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${REBASE_USER_ROLE}')
2904
- AND to_regclass('${qualified}') IS NOT NULL THEN
2934
+ AND to_regclass('${qualified}') IS NOT NULL
2935
+ AND NOT (SELECT relrowsecurity FROM pg_class WHERE oid = to_regclass('${qualified}')) THEN
2905
2936
  EXECUTE 'REVOKE ALL ON ${qualified} FROM ${REBASE_USER_ROLE}';
2906
2937
  END IF;
2907
2938
  END