Require Explicit Kernel Aliases for Protected Package Removal
Decision date: 2026-11-11
Status: Released in pig v1.11.0, from implementation commita95f37f; the owner approved the package boundary, explicit aliases, and whole-request rejection on 2026-11-11.
Current reference:pig ext rm
Scope: Package selection forext 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;
--yesshould 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.