Repository navigation
Darling live tests stop depending on PUBLIC's CONNECT on the shared test database (#5618) - #5621
Merged
Merged
Conversation
…est database (#5618) The password-key live test ran the managed provisioning batch inside a scratch database; its REVOKE ALL ON DATABASE darling FROM PUBLIC landed on the cluster's shared darling database, and the redaction test's own login (CONNECT only through PUBLIC) was then refused with 42501. The managed case now points its database-level statements at its own scratch database, the redaction test grants its probe role CONNECT itself, and a guard on the pg-cluster-roles collection fails the test that leaves PUBLIC without CONNECT.
erikdarlingdata
marked this pull request as ready for review
October 9, 2026 05:33
erikdarlingdata
enabled auto-merge (squash)
October 9, 2026 05:35
erikdarlingdata
disabled auto-merge
October 9, 2026 05:58
4 of 5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude posting for Erik Darling.
This changes tests only. One Darling live test ran the managed provisioning batch inside a scratch database. That batch revokes CONNECT from PUBLIC on the database named
darling. Database privileges are shared by the whole cluster. So the shared test database lost them for every test after it.The nightly failure was a victim. The redaction test opens a connection as a fresh role, and a fresh role has CONNECT only through PUBLIC. The culprit now aims its batch at its own scratch database. The victim grants its own role CONNECT. A new guard fails the test that does this the next time, by name.
SECTION: none (test-only)
What failed
Nightly run 37880262182 (dev b76725f), Darling PostgreSQL job: 1 failed of 30114.
PgSettingRedactionLivePostgresTests.PrimaryConninfosPassword_IsRedactedByTheRealCollector_UnderAPgMonitorOnlyRole,42501: permission denied for database "darling"on the line that opens the test's own pg_monitor-only role.The cause (measured, one class)
I ran 21 candidate classes one at a time against a local PostgreSQL 17 (database
darling). Before and after each class I readhas_database_privilege('public', 'darling', 'CONNECT')and the database ACL. I restored PUBLIC's grant between classes. The candidates were these:EnsureProvisionedAsync.pg-cluster-roles.I did not measure the allow-list classes whose entry says they only feed sample statement text to a scrubber (four of them). I also did not measure
MigrationUpgradeLadderLiveTestsandComposeTempFileLimitLiveTests, because their entries say they write nothing at database level. I read them instead.Exactly one flips it, in every one of the five runs I made:
PasswordKeyTablesLiveTests. ACL before{=Tc/darling,darling=CTc/darling}, after{darling=CTc/darling}. The other 20 leave it untouched, includingAlertHistoryDismissTestslines 114 and 310 (the lead in the issue): it builds the text and never runs it.The test is
Provisioning_LeavesNoReadOfThePinTables_AndNoTriggerOrReferencesGrant_AfterAGrantAllRerun(managed: true). I turned onlog_statement = 'ddl'and ran just that method. The server log showsREVOKE ALL ON DATABASE darling FROM PUBLICarriving twice (the test reruns the batch) on a session whose database isdarling_scratch_.... It shows none formanaged: false. After the method PUBLIC reads false. The ComposeStore case does not do it, because that target leaves the revoke out.The same measurement, plus reading, ruled out these causes:
REVOKE CONNECT,ALTER DATABASEondarling, and a drop or recreate ofdarling.DarlingCliCommandsHostCheckTestscreates it only when absent and drops only what it created.DarlingStoreUpgradeTestsruns on its own cluster.Why it showed up after #5604: inferred, not measured. #5604 moved both
PasswordKeyTablesLiveTestsand the redaction class fromlive-postgres(about sixty classes) intopg-cluster-roles(nine). Classes inside one collection run one at a time in an order xUnit picks, and I did not look into the rule.Whether the redaction test runs before or after the revoking test depends on that order. The move changed it for CI. In my local run of the two classes together, the redaction test ran first and passed. PUBLIC ended revoked. Nothing in the suite puts the grant back, so the first test to need it after the revoke fails.
What changes
PgSettingRedactionLivePostgresTests.cs:78and:168: the probe role is granted CONNECT on the database the test connects to. The grant is revoked in the cleanup before the role is dropped. A role that holds a privilege cannot be dropped. The revoke is guarded for a body that failed before creating the role. Every existing assertion is unchanged. The class comment said "live-postgres collection". It now sayspg-cluster-roles.PasswordKeyTablesLiveTests.cs:292-315: the managed case keeps the managed shape (owner, role marker, the PUBLIC revoke). Its three database-level statements are now pointed at the test's own scratch database, the wayViewerGrantReplayalready does for its replays.darlingdatabase" is gone, because the test no longer touches that database. The owner check stays.PublicConnectGuardAttribute.cs(new) onPgClusterRolesCollection.cs:41: an xUnit before/after attribute on the collection. Before and after every test, it reads PUBLIC's CONNECT on the databaseDARLING_TEST_PGnames and ondarling. It fails the test where a granted privilege became revoked. It compares before with after instead of demanding a grant. So a developer's own managed store (revoked on purpose) does not fail everything. It does nothing withoutDARLING_TEST_PG. I did not touchScratchPostgres. Its comment says a dispose must not fail a passing test. The guard fits the collection that is the only home of this kind of test.PublicConnectDelta.cs(new): the comparison, store-free so a guard-stage test can pin it.PublicConnectGuardTests.cs(guard stage): the comparison.PublicConnectCatalogReadLiveTests.cs: the catalog read against a real cluster, on a scratch database, and a pin thatPgClusterRolesCollectionstill carries the attribute.ScratchPostgreschange.RED proofs
REVOKE ALL ON DATABASE darling FROM PUBLIC, then the old test:Failed: 1,42501: permission denied for database "darling". The new test on the same state:Total: 1, Failed: 0. The database ACL after is{darling=CTc/darling}(no leftover grant) and no leftover role. PUBLIC restored withGRANT CONNECT, TEMPORARY ON DATABASE darling TO PUBLIC.PasswordKeyTablesLiveTestsleaves the probe at false. After the fix, true (ACL unchanged).PasswordKeyTablesLiveTests. Then the class reportsTotal: 6, Failed: 1. Themanaged: Truecase fails with "... left PUBLIC without CONNECT on database "darling" (A Darling live test fails when another test leaves PUBLIC without CONNECT on the shared test database #5618) ...", and nothing else fails. With the retarget restored, 0 failed.Test plan
pg-cluster-rolesmember, in one process (the shape of CI): Total 56, Failed 0, Skipped 1. PUBLIC's CONNECT ondarlingtrue afterwards.PublicConnect*: Total 3, Failed 0.*Census*Total 499, Failed 0.*Ratchet*15 / 0.*Hygiene*90 / 0.*Scrub*123 / 0.*Guard*365 / 0.Stage=Guard1469 / 0. All on the final head after merging origin/dev.pg-cluster-rolescollection together with the parallel collections.Not done
Nothing was left undone. One thing to look at: the guard covers the
pg-cluster-rolescollection only. A class outside it that revokes PUBLIC's CONNECT is still found by the victim's name.PgClusterObjectCensusTestskeeps such classes inside that collection or on its allow list. Such classes are those that name the managed batch or a database-level statement. I measured every allow-listed class except the six named under the cause, which I read instead.Fixes #5618