From adb779247dbb8ca487c2c430302357635f43e657 Mon Sep 17 00:00:00 2001 From: jnasbyupgrade Date: Sat, 29 Aug 2026 17:52:45 -0500 Subject: [PATCH] Document `superuser` and `trusted`; split general PostgreSQL guidance into its own docs Neither README.asc nor CLAUDE.md said anything about the `.control` file parameters that decide who may run `CREATE EXTENSION`. Both are now covered, but in new files rather than in the existing docs: this material is about PostgreSQL itself, not about pgxntool, and mixing the two makes it unclear which claims pgxntool is actually responsible for. - `POSTGRES-NOTES.asc` (human-facing): `superuser = false` drops the superuser requirement and runs the script as the caller, who must already hold every privilege it needs; `trusted = true` lets a non-superuser with CREATE on the database install it but runs the script as the bootstrap superuser, is only consulted when `superuser` is true, and needs PG13+. Carries the security warning and links PostgreSQL's own security-considerations section. - `CLAUDE-POSTGRES.md` (agent-facing): agents reach for `trusted = true` as the quick answer to "let a non-superuser install this" and present it bare, which reads as a recommendation for what is actually a privilege-escalation surface. Rule: `trusted` may never be mentioned without also offering `superuser = false` and stating the security consequences. One-directional -- `superuser = false` on its own is fine. `README.asc` and `CLAUDE.md` each gain a pointer to their counterpart; CLAUDE.md also uses an `@` import so the rules load automatically where that is supported. The "never produce metrics or estimates without data" rule moves to CLAUDE-POSTGRES.md, where it belongs -- it has nothing to do with pgxntool and was orphaned under "Related Repositories". Both new files are already covered by `.gitattributes` (`*.asc`, `*.md` are export-ignored), so they reach subtree consumers but not PGXN distributions. Co-Authored-By: Claude Opus 5 (1M context) --- CLAUDE-POSTGRES.md | 38 ++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 13 +++++++++++-- POSTGRES-NOTES.asc | 43 +++++++++++++++++++++++++++++++++++++++++++ README.asc | 7 +++++++ 4 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 CLAUDE-POSTGRES.md create mode 100644 POSTGRES-NOTES.asc diff --git a/CLAUDE-POSTGRES.md b/CLAUDE-POSTGRES.md new file mode 100644 index 0000000..03b84b3 --- /dev/null +++ b/CLAUDE-POSTGRES.md @@ -0,0 +1,38 @@ +# General PostgreSQL Guidance + +Guidance in this file is about **PostgreSQL itself** rather than about pgxntool -- it +applies just as much in a project that has never heard of pgxntool. `CLAUDE.md`, next to +this file, covers pgxntool proper. + +As with `CLAUDE.md`, an extension project's own CLAUDE.md and instructions take +precedence over anything here. + +The human-facing version of this material is `POSTGRES-NOTES.asc`. + +## Never Mention `trusted` Without `superuser = false` and the Security Caveat + +Whenever you bring up the `trusted` control-file parameter -- in code, a comment, a +document, a commit message, a PR, or a chat reply -- you MUST in the same breath also: + +1. Offer `superuser = false` as the alternative, and +2. State that `trusted = true` carries security consequences, pointing at PostgreSQL's + [Security Considerations for Extensions](https://www.postgresql.org/docs/current/extend-extensions.html#EXTEND-EXTENSIONS-SECURITY) + rather than reassuring the reader yourself. + +The rule is one-directional: mentioning `superuser = false` on its own is fine. It is +specifically `trusted` that must never appear unaccompanied. + +**Why**: `trusted = true` is the answer that comes to mind fastest for "how do I let a +non-superuser install this?", so raising it alone reads as a recommendation. It isn't a +free switch -- it runs the install script as the bootstrap superuser on behalf of an +unprivileged caller, which turns any flaw in that script into privilege escalation. +`superuser = false` solves the same problem while granting nothing: the caller simply +needs the privileges the script actually uses. When the extension doesn't require +superuser-only capabilities, that's the better suggestion. + +See `POSTGRES-NOTES.asc` for the user-facing explanation of both parameters. + +## Metrics and Estimates + +Never produce any kind of metrics or estimates unless you have data to back them up. If +you do have data you MUST reference it. diff --git a/CLAUDE.md b/CLAUDE.md index 65e3bf7..17ca775 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,6 +30,16 @@ development must be done from the **pgxntool-test** repository, not from here. S Any agent working in an extension project should always defer to that project's own CLAUDE.md and instructions over anything stated here. +Guidance that is about PostgreSQL itself rather than about pgxntool lives in +`CLAUDE-POSTGRES.md` instead, so that this file stays about pgxntool. + +## Read `CLAUDE-POSTGRES.md` + +**`CLAUDE-POSTGRES.md` (next to this file) contains rules you must follow.** The `@` line +below imports it where that is supported; read the file directly if it did not. + +@CLAUDE-POSTGRES.md + ## Git Commit Guidelines **IMPORTANT**: When creating commit messages, do not attribute commits to yourself (Claude). Commit messages should reflect the work being done without AI attribution in the message body. The standard Co-Authored-By trailer is acceptable. @@ -288,5 +298,4 @@ may lack such a header. ## Related Repositories -- **pgxntool-test** - Test harness for validating pgxntool functionality: https://github.com/Postgres-Extensions/pgxntool-test -- Never produce any kind of metrics or estimates unless you have data to back them up. If you do have data you MUST reference it. \ No newline at end of file +- **pgxntool-test** - Test harness for validating pgxntool functionality: https://github.com/Postgres-Extensions/pgxntool-test \ No newline at end of file diff --git a/POSTGRES-NOTES.asc b/POSTGRES-NOTES.asc new file mode 100644 index 0000000..ea1001c --- /dev/null +++ b/POSTGRES-NOTES.asc @@ -0,0 +1,43 @@ += General PostgreSQL Notes +Not about PGXNtool +:sectlinks: +:sectanchors: +:toc: + +This file collects guidance about *PostgreSQL itself* rather than about PGXNtool. It +lives here because these questions come up constantly while writing an extension, and +PGXNtool's docs are where extension authors already are. Nothing here describes +PGXNtool behavior, and nothing PGXNtool does depends on it. + +For PGXNtool's own documentation, see link:README.asc[README.asc]. + +== Who Can Install Your Extension: `superuser` and `trusted` + +By default only a superuser can run `CREATE EXTENSION` or `ALTER EXTENSION ... UPDATE` +for your extension. Two `.control` file parameters change that. + +`superuser = false`:: +Removes the superuser requirement outright. The install/update script then runs as the +user who invoked `CREATE EXTENSION`, so that user must already hold every privilege the +script needs -- nothing is granted implicitly. + +`trusted = true`:: +Lets any non-superuser with `CREATE` privilege on the database install the extension, +but runs the install/update script as the *bootstrap superuser* instead of as the +caller. It is only consulted when `superuser` is true (the default), and requires +PostgreSQL 13 or later. + +WARNING: `trusted = true` has real security consequences. Because the script runs with +superuser rights on behalf of an unprivileged caller, any weakness in it becomes a +privilege-escalation path, and writing a trusted extension's SQL safely takes deliberate +effort. Read PostgreSQL's own +https://www.postgresql.org/docs/current/extend-extensions.html#EXTEND-EXTENSIONS-SECURITY[Security +Considerations for Extensions] before setting it. + +If your extension doesn't need superuser-only capabilities, `superuser = false` is +usually the better of the two: it grants nothing, it merely stops requiring superuser. + +PostgreSQL's reference documentation for both parameters: +https://www.postgresql.org/docs/current/extend-extensions.html#EXTEND-EXTENSIONS-FILES-SUPERUSER[`superuser`] +and +https://www.postgresql.org/docs/current/extend-extensions.html#EXTEND-EXTENSIONS-FILES-TRUSTED[`trusted`]. diff --git a/README.asc b/README.asc index 45c4b59..ce69161 100644 --- a/README.asc +++ b/README.asc @@ -736,6 +736,13 @@ Default: `yes`. Sub-check of check-stale-expected, independent of `PGXNTOOL_ENAB Default: unset (PGXS is included normally). Skips including PGXS (`$(PGXS)`) entirely. This is only for advanced scenarios where you need to manage the PGXS include yourself; most projects should never set this. +== General PostgreSQL Notes + +link:POSTGRES-NOTES.asc[POSTGRES-NOTES.asc] collects guidance about PostgreSQL itself +rather than about PGXNtool -- things that come up constantly while writing an extension +but that PGXNtool has no part in. It currently covers which `.control` file parameters +(`superuser`, `trusted`) control who is allowed to install your extension. + == Copyright Copyright (c) 2026 Jim Nasby