Skip to content

Follow-on to #18: run application-level tests as a genuine non-superuser - #45

Open
jnasbyupgrade wants to merge 4 commits into
masterfrom
followon/nonsuperuser-test-coverage
Open

jnasbyupgrade wants to merge 4 commits into
masterfrom
followon/nonsuperuser-test-coverage

Conversation

@jnasbyupgrade

@jnasbyupgrade jnasbyupgrade commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Follow-on to #18: run more of the application-level test suite as a genuine non-superuser.

(Replaces #30, which developed a stuck head/diff computation on GitHub's side that survived a
force-push, a base-branch retarget, and a close/reopen — confirmed by opening this PR against the
exact same commits, which computed correctly immediately. Same content, same history.)

Background

While updating #18, the question came up: could we run more of this test suite as a non-superuser, given #18 was exactly the kind of bug (SET ROLE permission check) that a superuser-run test suite can't naturally catch?

test/helpers/create.sql switches into a non-superuser test_role for most of base.sql/pgtap.sql -- but via SET ROLE, not SET SESSION AUTHORIZATION. That distinction matters: SET ROLE only changes current_user; Postgres's own permission check for a further SET ROLE (the exact class of check #18's bug was in) is based on session_user, which SET ROLE leaves untouched. Under pg_regress's superuser connection, that silently bypassed this whole class of check for the rest of the file. Fixed by switching to SET SESSION AUTHORIZATION. Also added test/sql/security.sql, proving the public tf.* API needs nothing beyond a freshly-created, unprivileged role -- using a new bare_role entry in test/roles.sql (this repo's single-source-of-truth pattern for test-only role names) rather than a literal role name.

Scope note: an earlier version of this PR also added a separate non-superuser CREATE EXTENSION repro (a disposable installer role in test/sql/install.sql). That's dropped -- test/install/load.sql's fresh/update branch (landed as part of #18's own review iterations, now on master) already does exactly this as the real install for the whole suite, making the separate repro redundant; test/sql/install.sql itself was deleted upstream for the same reason. This PR is based on current master and contains only the still-missing piece.

Test plan

  • make test -- load/base/pgtap pass; security runs correctly (4/4 pgtap assertions pass) but needs make results to accept its expected output, per this repo's human-verifies-expected-output convention
  • make test-update -- same result
  • make lint -- clean
  • test/expected/base.out/pgtap.out unchanged

🤖 Generated with Claude Code

jnasbyupgrade and others added 2 commits August 17, 2026 15:07
…low-on)

test/helpers/create.sql now uses SET SESSION AUTHORIZATION instead of
SET ROLE to switch into test_role. SET ROLE only changes current_user;
a further SET ROLE's own permission check (like the one test_factory's
install performs, and like issue #14's bug) is based on session_user,
which SET ROLE leaves untouched. Under pg_regress's superuser
connection, that means SET ROLE alone silently leaves this whole class
of check bypassed for the rest of the file -- SET SESSION AUTHORIZATION
actually drops it.

New test/sql/security.sql proves the public tf.* API needs nothing
beyond what a freshly-created, unprivileged role gets by default (no
owned schema, no explicit grants, not a member of test_factory__owner):
register/get work end to end, and the role still can't SET ROLE into
test_factory__owner.

The non-superuser CREATE EXTENSION repro this PR originally added
separately (a disposable test_factory_installer role in
test/sql/install.sql) is dropped: test/install/load.sql's fresh/update
branch now does exactly this, as the real install for the whole suite,
making that separate repro redundant. test/sql/install.sql itself was
already deleted upstream for the same reason.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Matches test_role/installer_role's existing pattern in test/roles.sql: a
role name that other files might need should be defined there once, not
inlined, so a rename only touches one place.

Also converts the resulting/existing 2+-line -- comment stacks in
roles.sql and security.sql to /* */, per the comment-stacked-dashes lint
rule tightened in the linter submodule after this branch's original
commits were written (2026-08-12, well after this branch's last real CI
run on 2026-07-30) -- not a rule violation introduced by this change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 58fc4e02-9654-4505-9979-ddc91e6fabc2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jnasbyupgrade jnasbyupgrade changed the title test Follow-on to #18: run application-level tests as a genuine non-superuser Sep 15, 2026
Hand-copied from test/results/ rather than via `make results`: that target's
verify-results-pgtap.sh safeguard can't accept a brand-new test file's first
baseline (any diff from no-baseline-yet trips its regression.diffs fallback
check, even with zero real `not ok` lines) -- filed as
Postgres-Extensions/pgxntool#119. Content verified directly: 4/4 real pgtap
assertions pass, nothing else in the file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread test/sql/security.sql Outdated
\i test/helpers/setup.sql

/*
* Prove the public tf.* API needs nothing beyond what a freshly-created,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a separate test? Can't we just have all the existing tests ensure they're using a bare role?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, you're right — checked it concretely: test_role owns nothing test_factory-related (no tf/_tf beyond what PUBLIC gets, and deliberately no test_factory__owner membership), so base.sql/pgtap.sql already proved the positive claim this file existed for. The only real gap was that nothing actually asserted the negative claim the comment next to the GRANT only stated as intent.

Fixed in 14c070c: added isnt_member_of('test_factory__owner', :test_role, ...) right at that comment in create.sql (pgtap's purpose-built membership check, cleaner than throws_ok on a live SET ROLE and version-independent), and deleted security.sql/bare_role entirely as redundant.

test_role owns nothing test_factory-related (no tf/_tf ownership beyond
what PUBLIC already gets, and -- per create.sql's own comment -- deliberately
no test_factory__owner membership), so base.sql/pgtap.sql running under
test_role already proved the positive claim security.sql existed for
(register/get works with nothing beyond default + tap grants). The only
gap was that nothing actually asserted the negative claim the comment only
stated as intent. Closed with pgtap's isnt_member_of(), which checks the
pg_auth_members row directly -- simpler than throws_ok on a live SET ROLE,
and version-independent (no PG16 SET-option branching needed).

security.sql, its expected output, and the now-unused bare_role are
removed as redundant.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant