From 44a5601d2132c53fffdd138a440e2dd9d47a5bd1 Mon Sep 17 00:00:00 2001 From: Utkarash Singh Date: Mon, 26 Oct 2026 11:13:09 +0000 Subject: [PATCH 1/5] feat: bump supautils to 4.0.0 and vault to 0.3.2, set default extension install schema --- ansible/files/postgresql_config/supautils.conf.j2 | 1 + ansible/postgres_release.yml | 6 +++--- nix/ext/supautils.nix | 4 ++-- nix/ext/versions.json | 7 +++++++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ansible/files/postgresql_config/supautils.conf.j2 b/ansible/files/postgresql_config/supautils.conf.j2 index 63c10761b5..7ee738634c 100644 --- a/ansible/files/postgresql_config/supautils.conf.j2 +++ b/ansible/files/postgresql_config/supautils.conf.j2 @@ -8,6 +8,7 @@ supautils.drop_trigger_grants = '{"postgres":["auth.audit_log_entries","auth.flo # omitted because protected: plpgsql # NOTE: keep nix/tests/prime-superuser.sql in sync with the "may be unsafe" + "deprecated" lists above. supautils.privileged_extensions = 'address_standardizer, address_standardizer_data_us, amcheck, autoinc, bloom, btree_gin, btree_gist, citext, cube, dblink, dict_int, dict_xsyn, earthdistance, fuzzystrmatch, hstore, http, hypopg, index_advisor, insert_username, intarray, isn, ltree, moddatetime, orioledb, pg_buffercache, pg_cron, pg_graphql, pg_hashids, pg_jsonschema, pg_net, pg_prewarm, pg_repack, pg_stat_monitor, pg_stat_statements, pg_tle, pg_trgm, pg_walinspect, pgaudit, pgcrypto, pgjwt, pgroonga, pgroonga_database, pgrouting, pgrowlocks, pgsodium, pgstattuple, pgtap, plcoffee, pljava, plls, plpgsql_check, plv8, postgis, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, postgis_topology, postgres_fdw, refint, rum, seg, sslinfo, supabase_vault, supautils, tablefunc, tcn, timescaledb, tsm_system_rows, tsm_system_time, unaccent, uuid-ossp, vector, wrappers' +supautils.default_extension_install_schema = 'extensions' supautils.extension_custom_scripts_path = '/etc/postgresql-custom/extension-custom-scripts' supautils.restrict_extension_versions = 'warn' supautils.privileged_extensions_superuser = 'supabase_admin' diff --git a/ansible/postgres_release.yml b/ansible/postgres_release.yml index 66379d530a..061a284cb1 100644 --- a/ansible/postgres_release.yml +++ b/ansible/postgres_release.yml @@ -1,5 +1,5 @@ --- postgres_release: - postgresorioledb-17: "17.11.0.011-orioledb" - postgres17: "17.11.0.011" - postgres15: "15.19.0.011" + postgresorioledb-17: "17.11.0.012-orioledb" + postgres17: "17.11.0.012" + postgres15: "15.19.0.012" diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index fcab1c3fce..600f0833a8 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -8,7 +8,7 @@ stdenv.mkDerivation rec { pname = "supautils"; name = pname; - version = "3.4.4"; + version = "4.0.0"; buildInputs = [ postgresql ]; @@ -21,7 +21,7 @@ stdenv.mkDerivation rec { owner = "supabase"; repo = pname; rev = "refs/tags/v${version}"; - hash = "sha256-Wsou5U7/Tuwj2E6aPEmlHg7uz7kGyBOGrb7UkjfEo9U="; + hash = "sha256-2tH34+JdgNqaR5ihtdJJQSIdT7zI4NTRHlYuEEO6/f8="; }; # remove once all Ubuntu 20.04 (glibc 2.31) hosts are decommissioned diff --git a/nix/ext/versions.json b/nix/ext/versions.json index 0c6c5b63a2..d6c4a526ea 100644 --- a/nix/ext/versions.json +++ b/nix/ext/versions.json @@ -573,6 +573,13 @@ "17" ], "hash": "sha256-MC87bqgtynnDhmNZAu96jvfCpsGDCPB0g5TZfRQHd30=" + }, + "0.3.2": { + "postgresql": [ + "15", + "17" + ], + "hash": "sha256-TH5caaDajqZosEuv50o0ec5vxQI1TkIIprKDCFF4z1k=" } }, "timescaledb": { From 90a6cd956d1bef81107e70db86bd2acab8815e33 Mon Sep 17 00:00:00 2001 From: Utkarash Singh Date: Mon, 26 Oct 2026 11:16:26 +0000 Subject: [PATCH 2/5] fix: drop constrained_extensions hunk from glibc compat patch, file removed in supautils 4.0.0 --- .../supautils-strtol-glibc-compat.patch | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 8c36e613d9..6fefe6e2c6 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -1,32 +1,3 @@ -diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c -index 18e5aee..cdfb63f 100644 ---- a/src/constrained_extensions.c -+++ b/src/constrained_extensions.c -@@ -9,6 +9,24 @@ - #include "constrained_extensions.h" - #include "utils.h" - -+#if defined(__linux__) && defined(__GLIBC__) && (defined(__x86_64__) || defined(__aarch64__)) -+# if defined(__x86_64__) -+# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.2.5" -+# else -+# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" -+# endif -+extern void *dlvsym(void *handle, const char *symbol, const char *version); -+__asm__(".symver dlvsym,dlvsym@" SUPAUTILS_GLIBC_COMPAT_VER); -+static int -+_supautils_compat_atoi(const char *nptr) -+{ -+ long (*fn)(const char *, char **, int) = -+ (long (*)(const char *, char **, int)) dlvsym((void *) 0, "strtol", SUPAUTILS_GLIBC_COMPAT_VER); -+ return fn ? (int) fn(nptr, NULL, 10) : 0; -+} -+#define atoi(a) _supautils_compat_atoi(a) -+#endif -+ - static JSON_ACTION_RETURN_TYPE json_array_start(void *state) { - json_constrained_extension_parse_state *parse = state; - diff --git a/src/extension_custom_scripts.c b/src/extension_custom_scripts.c index 337bd69..3f285cc 100644 --- a/src/extension_custom_scripts.c From 98b151d4ed3d10d301ec5ef477568a09c49b6540 Mon Sep 17 00:00:00 2001 From: Utkarash Singh Date: Mon, 26 Oct 2026 11:30:09 +0000 Subject: [PATCH 3/5] fix: create vault's generic library symlink in buildEnv instead of per-version packages With two library-bearing vault versions, the per-version symlink to the latest dylib dangles inside the older version's package and fails the noBrokenSymlinks check. Follow the timescaledb pattern: link once in postBuild. --- nix/ext/vault.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nix/ext/vault.nix b/nix/ext/vault.nix index 9ab5391b1d..762e5121de 100644 --- a/nix/ext/vault.nix +++ b/nix/ext/vault.nix @@ -73,7 +73,6 @@ let cat $out/share/postgresql/extension/${pname}--${latestVersion}.control } > $out/share/postgresql/extension/${pname}.control fi - ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} ''; meta = with lib; { @@ -94,6 +93,9 @@ pkgs.buildEnv { ]; postBuild = '' + # Point the generic library name at the latest version + ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + makeWrapper ${lib.getExe switch-ext-version} $out/bin/switch_${pname}_version \ --prefix EXT_WRAPPER : "$out" --prefix EXT_NAME : "${pname}" ''; From c3b09e650565bbfa1da1274bf69cbbb719c91423 Mon Sep 17 00:00:00 2001 From: Utkarash Singh Date: Mon, 26 Oct 2026 12:30:13 +0000 Subject: [PATCH 4/5] fix: ship each vault version's own base install script, adapt tests to default extension install schema vault 0.3.2 removed the deprecated supabase_vault--0.2.8.sql base script from its tree, so shipping sql files only from the latest version made CREATE EXTENSION supabase_vault VERSION '0.2.8' fail while versions.json still offers 0.2.8. Install each version's own base script from its own source. pgrst_watch_triggers called dblink via a hardcoded public. qualifier; dblink now installs into extensions. --- nix/ext/vault.nix | 8 ++++++++ nix/tests/expected/evtrigs.out | 4 ++-- nix/tests/expected/pgrst_watch_triggers.out | 10 +++++----- nix/tests/sql/pgrst_watch_triggers.sql | 10 +++++----- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/nix/ext/vault.nix b/nix/ext/vault.nix index 762e5121de..78fb60938d 100644 --- a/nix/ext/vault.nix +++ b/nix/ext/vault.nix @@ -59,6 +59,14 @@ let -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \ ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control + # Install this version's base install script from its own source. + # Newer sources drop deprecated base scripts (e.g. 0.3.2 removed + # supabase_vault--0.2.8.sql), so the latest version's sql/ alone + # can't install every packaged version. + if [ -f sql/${pname}--${version}.sql ]; then + install -D -t $out/share/postgresql/extension sql/${pname}--${version}.sql + fi + '' # for versions <= 0.2.8, we don't have a library to install + lib.optionalString (builtins.compareVersions "0.2.8" version < 0) '' diff --git a/nix/tests/expected/evtrigs.out b/nix/tests/expected/evtrigs.out index 84f3e27058..0313d57f84 100644 --- a/nix/tests/expected/evtrigs.out +++ b/nix/tests/expected/evtrigs.out @@ -20,8 +20,8 @@ order by e.evtname; issue_pg_graphql_access | supabase_admin | extensions | grant_pg_graphql_access | supabase_admin issue_pg_net_access | supabase_admin | extensions | grant_pg_net_access | supabase_admin pg_tle_event_trigger_for_drop_function | supabase_admin | pgtle | pgtle.pg_tle_feature_info_sql_drop | supabase_admin - pgaudit_ddl_command_end | supabase_admin | public | pgaudit_ddl_command_end | supabase_admin - pgaudit_sql_drop | supabase_admin | public | pgaudit_sql_drop | supabase_admin + pgaudit_ddl_command_end | supabase_admin | extensions | pgaudit_ddl_command_end | supabase_admin + pgaudit_sql_drop | supabase_admin | extensions | pgaudit_sql_drop | supabase_admin pgrst_ddl_watch | supabase_admin | extensions | pgrst_ddl_watch | supabase_admin pgrst_drop_watch | supabase_admin | extensions | pgrst_drop_watch | supabase_admin pgsodium_trg_mask_update | supabase_admin | pgsodium | pgsodium.trg_mask_update | supabase_admin diff --git a/nix/tests/expected/pgrst_watch_triggers.out b/nix/tests/expected/pgrst_watch_triggers.out index 0a161fb1c6..47911b70cc 100644 --- a/nix/tests/expected/pgrst_watch_triggers.out +++ b/nix/tests/expected/pgrst_watch_triggers.out @@ -12,7 +12,7 @@ -- returns how many notifications it received since the previous call. The -- notifying backend PID is left out so the output is deterministic. set client_min_messages = warning; -select public.dblink_connect( +select extensions.dblink_connect( 'pgrst_listener', format('host=localhost port=%s dbname=%s user=supabase_admin', current_setting('port'), current_database()) @@ -22,7 +22,7 @@ select public.dblink_connect( OK (1 row) -select public.dblink_exec('pgrst_listener', 'LISTEN pgrst'); +select extensions.dblink_exec('pgrst_listener', 'LISTEN pgrst'); dblink_exec ------------- LISTEN @@ -32,8 +32,8 @@ create function pg_temp.pgrst_reloads() returns bigint language plpgsql as $$ begin -- round trip so the listener has flushed any pending notification - perform from public.dblink('pgrst_listener', 'SELECT 1') as t(x int); - return (select count(*) from public.dblink_get_notify('pgrst_listener') + perform from extensions.dblink('pgrst_listener', 'SELECT 1') as t(x int); + return (select count(*) from extensions.dblink_get_notify('pgrst_listener') where notify_name = 'pgrst' and extra = 'reload schema'); end $$; -- Setup, notifications drained below. auth, realtime and storage come from @@ -329,7 +329,7 @@ select pg_temp.pgrst_reloads() as drop_schema; -- Cleanup drop schema _realtime; -select public.dblink_disconnect('pgrst_listener'); +select extensions.dblink_disconnect('pgrst_listener'); dblink_disconnect ------------------- OK diff --git a/nix/tests/sql/pgrst_watch_triggers.sql b/nix/tests/sql/pgrst_watch_triggers.sql index cce4c0d1e9..9d75b69bc9 100644 --- a/nix/tests/sql/pgrst_watch_triggers.sql +++ b/nix/tests/sql/pgrst_watch_triggers.sql @@ -14,19 +14,19 @@ set client_min_messages = warning; -select public.dblink_connect( +select extensions.dblink_connect( 'pgrst_listener', format('host=localhost port=%s dbname=%s user=supabase_admin', current_setting('port'), current_database()) ); -select public.dblink_exec('pgrst_listener', 'LISTEN pgrst'); +select extensions.dblink_exec('pgrst_listener', 'LISTEN pgrst'); create function pg_temp.pgrst_reloads() returns bigint language plpgsql as $$ begin -- round trip so the listener has flushed any pending notification - perform from public.dblink('pgrst_listener', 'SELECT 1') as t(x int); - return (select count(*) from public.dblink_get_notify('pgrst_listener') + perform from extensions.dblink('pgrst_listener', 'SELECT 1') as t(x int); + return (select count(*) from extensions.dblink_get_notify('pgrst_listener') where notify_name = 'pgrst' and extra = 'reload schema'); end $$; @@ -173,4 +173,4 @@ select pg_temp.pgrst_reloads() as drop_schema; -- Cleanup drop schema _realtime; -select public.dblink_disconnect('pgrst_listener'); +select extensions.dblink_disconnect('pgrst_listener'); From 8928344e9e3a2b17d1de558a5c5a79de3f1ba056 Mon Sep 17 00:00:00 2001 From: Utkarash Singh Date: Mon, 26 Oct 2026 14:16:47 +0000 Subject: [PATCH 5/5] revert: drop the default extension install schema setting, landing separately with salt sync and a breaking change announcement --- ansible/files/postgresql_config/supautils.conf.j2 | 1 - nix/tests/expected/evtrigs.out | 4 ++-- nix/tests/expected/pgrst_watch_triggers.out | 10 +++++----- nix/tests/sql/pgrst_watch_triggers.sql | 10 +++++----- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ansible/files/postgresql_config/supautils.conf.j2 b/ansible/files/postgresql_config/supautils.conf.j2 index 7ee738634c..63c10761b5 100644 --- a/ansible/files/postgresql_config/supautils.conf.j2 +++ b/ansible/files/postgresql_config/supautils.conf.j2 @@ -8,7 +8,6 @@ supautils.drop_trigger_grants = '{"postgres":["auth.audit_log_entries","auth.flo # omitted because protected: plpgsql # NOTE: keep nix/tests/prime-superuser.sql in sync with the "may be unsafe" + "deprecated" lists above. supautils.privileged_extensions = 'address_standardizer, address_standardizer_data_us, amcheck, autoinc, bloom, btree_gin, btree_gist, citext, cube, dblink, dict_int, dict_xsyn, earthdistance, fuzzystrmatch, hstore, http, hypopg, index_advisor, insert_username, intarray, isn, ltree, moddatetime, orioledb, pg_buffercache, pg_cron, pg_graphql, pg_hashids, pg_jsonschema, pg_net, pg_prewarm, pg_repack, pg_stat_monitor, pg_stat_statements, pg_tle, pg_trgm, pg_walinspect, pgaudit, pgcrypto, pgjwt, pgroonga, pgroonga_database, pgrouting, pgrowlocks, pgsodium, pgstattuple, pgtap, plcoffee, pljava, plls, plpgsql_check, plv8, postgis, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, postgis_topology, postgres_fdw, refint, rum, seg, sslinfo, supabase_vault, supautils, tablefunc, tcn, timescaledb, tsm_system_rows, tsm_system_time, unaccent, uuid-ossp, vector, wrappers' -supautils.default_extension_install_schema = 'extensions' supautils.extension_custom_scripts_path = '/etc/postgresql-custom/extension-custom-scripts' supautils.restrict_extension_versions = 'warn' supautils.privileged_extensions_superuser = 'supabase_admin' diff --git a/nix/tests/expected/evtrigs.out b/nix/tests/expected/evtrigs.out index 0313d57f84..84f3e27058 100644 --- a/nix/tests/expected/evtrigs.out +++ b/nix/tests/expected/evtrigs.out @@ -20,8 +20,8 @@ order by e.evtname; issue_pg_graphql_access | supabase_admin | extensions | grant_pg_graphql_access | supabase_admin issue_pg_net_access | supabase_admin | extensions | grant_pg_net_access | supabase_admin pg_tle_event_trigger_for_drop_function | supabase_admin | pgtle | pgtle.pg_tle_feature_info_sql_drop | supabase_admin - pgaudit_ddl_command_end | supabase_admin | extensions | pgaudit_ddl_command_end | supabase_admin - pgaudit_sql_drop | supabase_admin | extensions | pgaudit_sql_drop | supabase_admin + pgaudit_ddl_command_end | supabase_admin | public | pgaudit_ddl_command_end | supabase_admin + pgaudit_sql_drop | supabase_admin | public | pgaudit_sql_drop | supabase_admin pgrst_ddl_watch | supabase_admin | extensions | pgrst_ddl_watch | supabase_admin pgrst_drop_watch | supabase_admin | extensions | pgrst_drop_watch | supabase_admin pgsodium_trg_mask_update | supabase_admin | pgsodium | pgsodium.trg_mask_update | supabase_admin diff --git a/nix/tests/expected/pgrst_watch_triggers.out b/nix/tests/expected/pgrst_watch_triggers.out index 47911b70cc..0a161fb1c6 100644 --- a/nix/tests/expected/pgrst_watch_triggers.out +++ b/nix/tests/expected/pgrst_watch_triggers.out @@ -12,7 +12,7 @@ -- returns how many notifications it received since the previous call. The -- notifying backend PID is left out so the output is deterministic. set client_min_messages = warning; -select extensions.dblink_connect( +select public.dblink_connect( 'pgrst_listener', format('host=localhost port=%s dbname=%s user=supabase_admin', current_setting('port'), current_database()) @@ -22,7 +22,7 @@ select extensions.dblink_connect( OK (1 row) -select extensions.dblink_exec('pgrst_listener', 'LISTEN pgrst'); +select public.dblink_exec('pgrst_listener', 'LISTEN pgrst'); dblink_exec ------------- LISTEN @@ -32,8 +32,8 @@ create function pg_temp.pgrst_reloads() returns bigint language plpgsql as $$ begin -- round trip so the listener has flushed any pending notification - perform from extensions.dblink('pgrst_listener', 'SELECT 1') as t(x int); - return (select count(*) from extensions.dblink_get_notify('pgrst_listener') + perform from public.dblink('pgrst_listener', 'SELECT 1') as t(x int); + return (select count(*) from public.dblink_get_notify('pgrst_listener') where notify_name = 'pgrst' and extra = 'reload schema'); end $$; -- Setup, notifications drained below. auth, realtime and storage come from @@ -329,7 +329,7 @@ select pg_temp.pgrst_reloads() as drop_schema; -- Cleanup drop schema _realtime; -select extensions.dblink_disconnect('pgrst_listener'); +select public.dblink_disconnect('pgrst_listener'); dblink_disconnect ------------------- OK diff --git a/nix/tests/sql/pgrst_watch_triggers.sql b/nix/tests/sql/pgrst_watch_triggers.sql index 9d75b69bc9..cce4c0d1e9 100644 --- a/nix/tests/sql/pgrst_watch_triggers.sql +++ b/nix/tests/sql/pgrst_watch_triggers.sql @@ -14,19 +14,19 @@ set client_min_messages = warning; -select extensions.dblink_connect( +select public.dblink_connect( 'pgrst_listener', format('host=localhost port=%s dbname=%s user=supabase_admin', current_setting('port'), current_database()) ); -select extensions.dblink_exec('pgrst_listener', 'LISTEN pgrst'); +select public.dblink_exec('pgrst_listener', 'LISTEN pgrst'); create function pg_temp.pgrst_reloads() returns bigint language plpgsql as $$ begin -- round trip so the listener has flushed any pending notification - perform from extensions.dblink('pgrst_listener', 'SELECT 1') as t(x int); - return (select count(*) from extensions.dblink_get_notify('pgrst_listener') + perform from public.dblink('pgrst_listener', 'SELECT 1') as t(x int); + return (select count(*) from public.dblink_get_notify('pgrst_listener') where notify_name = 'pgrst' and extra = 'reload schema'); end $$; @@ -173,4 +173,4 @@ select pg_temp.pgrst_reloads() as drop_schema; -- Cleanup drop schema _realtime; -select extensions.dblink_disconnect('pgrst_listener'); +select public.dblink_disconnect('pgrst_listener');