Skip to content

Require Explicit Kernel Aliases for Protected Package Removal

A removal boundary based on the resolved package and the user’s original operand, while retaining independent language-package removal.

Decision date: 2026-11-11
Status: Released in pig v1.11.0, from implementation commit a95f37f; the owner approved the package boundary, explicit aliases, and whole-request rejection on 2026-11-11.
Current reference: pig ext rm
Scope: Package selection for ext rm; package-manager dependency simulation remains outside this scope.

Decision

Protect PostgreSQL server packages, shared contrib bundles, and supported replacement kernels. A protected package may be removed only through an explicitly registered kernel or package-group alias. An extension operand that resolves to the same package must be rejected before any package-manager invocation. Independent language packages remain removable through extension names.

The decision depends on both the final package and the original operand. Neither an extension’s contrib flag nor a postgresql package-name prefix is sufficient.

Context

The baseline resolver maps extension names and aliases to packages and deduplicates them before removal. On Debian, pg_trgm can resolve to postgresql-18; on EL it resolves to postgresql18-contrib. plpgsql resolves to the server itself. These are larger removal boundaries than the named extension. A fork extension such as spock can similarly resolve to its pgedge-18 kernel package.

PL/Python, PL/Tcl, and PL/Perl also have contrib metadata, but their OS packages are separate from the server and contrib bundle. PL/Tcl and PL/TclU share one language package, as do PL/Perl and PL/PerlU. Requiring literally one extension per package would reject valid language removal and ordinary multi-extension packages such as PostGIS.

Alternatives considered

  • Reject every contrib extension. This would also reject independent language packages.
  • Reject every shared package. Ordinary extension suites intentionally share packages.
  • Trust every alias. Category aliases can expand to catalog entries backed by kernels; being an alias alone does not establish deliberate kernel removal.
  • Allow a protected package whenever another operand authorizes it. This makes a mixed request hide an unsafe extension operand. Validate each operand before deduplication instead.
  • Offer a generic force flag. An explicit kernel alias expresses which package boundary the caller intends to remove; --yes should remain confirmation only.

Contract

Maintain a small code-owned registry of protected package templates and the explicit aliases authorized for them. Expand templates using the target version encoded in the alias when present. Match complete package names, including supported vendor kernel families; do not infer protection from a broad prefix or editable catalog flags alone. The registry covers the supported kernel families. Adding another family requires updating this code-owned boundary; catalog metadata alone neither adds protection nor authorizes a new removal alias.

The accepted behavior for a PostgreSQL 18 target:

Operand Resolved boundary Decision
pg_trgm, earthdistance, tablefunc Debian server or EL contrib bundle Reject
plpgsql Server Reject
plpython3u, pltcl, pltclu, plperl, plperlu Independent language package Allow
vector, postgis Ordinary extension package Allow
pg18-server, pgsql-server -v 18 Explicit server group Allow; show every package in that group
pg18, pg18-core, pg18-mini, pg18-full, pg18-main Explicit PostgreSQL group Allow the group’s registered protected packages
pg18-contrib Separate contrib bundle on EL Allow through this dedicated alias
pg18-contrib on Debian No separate bundle in the current mapping Reject; do not silently substitute the server
spock, snowflake, lolor pgEdge kernel Reject
pgedge -v 18 Explicit pgEdge kernel Allow
ivorysql_ora, babelfishpg_tsql, aux_mysql Replacement kernel Reject; name the corresponding kernel alias
pg18-etl, another category or unrelated group Any protected package Reject

Equivalent pgsql-* aliases use -v; existing postgresql and vendor kernel aliases are registered explicitly with their exact package scope. Existing version restrictions remain. An alias authorizes only its own package family and target major, never another operand.

orioledb currently names both an extension and a kernel alias. Preserve its extension meaning for the protection check and use an unambiguous orioledb-server alias for deliberate kernel removal. This avoids changing the meaning of an extension operand depending on lookup order.

Preserve, for each operand, its original spelling, resolution kind (extension, normalized extension package, explicit group, or category), matched alias, and complete package list. Check every operand before building the deduplicated command. If any operand requests a protected package through an unauthorized route, reject the entire removal, including otherwise safe operands; perform no sudo or package-manager call. Reordering operands must not change this.

Runtime and --plan share the same check. A blocked plan contains failed preconditions and no executable removal actions; runtime returns a specific protected-package parameter error. Runtime uses error code 100102; both return usage exit status 2. Diagnostics name the operand, resolved package, and required explicit alias without running or automatically confirming that alternative. --yes does not bypass protection. Existing package-manager confirmation remains in force.

An allowed plan describes package removal, including other extensions sharing an independent language or ordinary extension package. It does not claim that only one database extension will disappear. It also does not predict every dependency that APT or DNF may remove.

The same unintended-kernel-selection issue can affect ext update. Reusing the provenance check there is a separate proposed extension of scope; this removal design does not silently ban updates.

Consequences

Scripts removing bundled extensions must select the documented package boundary explicitly or manage database objects separately. Removing an independent PL package remains supported, even when the catalog marks it contrib or the package supplies trusted and untrusted variants.

This change requires updates to the bilingual extension reference, alias help, removal result errors, and plans. Install and category-list behavior should remain compatible.

Verification

Regression tests in a95f37f exercise both real catalog mappings and controlled resolver fixtures on Debian and EL across supported majors. They cover server and contrib rejection, language-package allowance, vendor kernels, the OrioleDB name collision, explicit aliases with a different -v, category expansion, mixed requests in both orders, duplicate packages, and --yes.

Rejected runtime requests assert zero calls to the package-manager adapter. Plans assert failed preconditions, no removal action, and the same rejection reason. Allowed aliases produce only the listed packages. Cobra tests verify text/JSON behavior and exit status using isolated fake executables rather than uninstalling host packages.

Current status

Implemented in source commit a95f37f, following owner approval on 2026-11-11. The current reference documents the approved contract, and the pinned source links above establish the original defect; the implementation is included in the v1.11.0 release artifacts.