Repository navigation
Let demo, local, and test run only alone and guard every profile against the demo users (B06) - #16
Closed
AsyncAssassin wants to merge 2 commits into
Closed
AsyncAssassin wants to merge 2 commits into
AsyncAssassin wants to merge 2 commits into
Conversation
…ected profile With SPRING_PROFILES_ACTIVE=prod,demo on a fresh database the demo-user guard ran first and found nothing, then the demo seeder wrote demo-reader and demo-operator with their public passwords, and the service ran with them until the next restart; the simulator path was open without credentials as well. prod combined with local failed, but on whichever bean it missed first. A bean factory post-processor now stops prod together with demo, local, or test before any bean is created, and names the active profiles. The demo seeder, the simulator, and the open /simulator path also require demo without prod. The demo-user guard was bound to the literal prod profile, so any other protected profile, e2e or a custom one such as staging, accepted the public demo passwords on a database that once ran demo. It now runs in every profile except demo, local, and test.
…r guard Review of the profile guard found that it only knew the literal prod: staging,demo still seeded the public demo users with the demo-user guard switched off, and staging,local started without authentication. It also ran after the configuration conditions, so prod,local without the prod secrets failed on an unresolved placeholder instead of naming the combination. The guard is now an environment post-processor that refuses demo, local, or test next to any other profile before the application context exists; the demo-only beans go back to plain demo, with this guard as the single point that keeps them out of prod. The demo-user guard is never lazy, skips a database without the users table instead of failing on its own query, names the default profile when none is active, and recommends an empty database, because a database the demo ran on also holds the demo dataset. The prod operator account cannot take a demo user name. The tests cover the profile matrix, start the refused combinations against an empty database that must stay empty, and assert the exact profiles in every message.
This was referenced Sep 23, 2026
Owner
Author
|
Combined into #23 together with the other batch-1 fixes, so they merge without a rebase per PR. This description keeps the detailed evidence for its fix. |
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.
Summary
B06 from the merged review of v0.4.0 (
prod,demobypassed the demo-user guard); 0.4.1 is released once all fixes are merged. A regression review of the first version showed that the guard only knew the literalprod, so this PR closes the whole class:demo,local, andtestrun only alone:SPRING_PROFILES_ACTIVE=prod,demoon a fresh database let the demo seeder writedemo-operatorafter the guard had checked, andstaging,demoorstaging,localhad the same gap without any guard.ProfileCombinationGuard, an environment post-processor registered inMETA-INF/spring.factories, now refuses any of these three next to another profile before the application context exists, and before a placeholder of the other profiles is resolved, soprod,localwithout the prod secrets names the combination instead of failing onASSET_SYNC_DB_URL. The demo-only beans keep plain@Profile("demo"); this guard is the single point that keeps them out of other profiles.demorefuses the demo users:ProdDemoUserGuardran only underprod. It now runs inprod,e2e, a custom profile such asstaging, and a start without any profile. It is@Lazy(false), sospring.main.lazy-initializationcannot skip it. It lets a database without theuserstable start instead of failing on its own query. Its message names the default profile when none is active and recommends an empty database, because a database the demo ran on also holds the demo dataset.CHANGELOG.mdlists both under[Unreleased]→ Security.Verification
./gradlew clean check: 280 tests, 0 failures, 2 skipped (the env-gated Alchemy live smoke).ProfileCombinationGuardTestspins the profile matrix. It covers which sets start, which are refused, and that the demo-user guard runs in exactly the sets that may start, exceptdemo.ProdProfileBootIntegrationTestsboots second contexts against the test container:prod,demo,prod,local,prod,test,staging,demo, andstaging,localare refused with their exact profiles, against a separate empty database that must stay empty;prod,localwithout the prod secrets is refused;prod,staging, and no profile refuse the demo users;stagingstarts on a database without theuserstable;demo-operatorfails.spring.factoriesregistration,prod,demostarts and the no-secrets case fails on a placeholder, so both tests go red.prod,demoandprod,localstop before migrations, andstagingandprodrefuse a database ademostart seeded.This PR and #15 both add a section under
[Unreleased]inCHANGELOG.md, so whichever merges second needs a one-file rebase. The other files merge cleanly with #15.