You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Related:#42, which adds the test. This is not an argument against that test, which caught
six invented keys across three rules. It is about what its failure message claims. #45 is
the concrete rule this currently blocks.
Summary
ConfigKeyMetadataTest fails any rule key missing from the vendored index of Spring Boot's
configuration metadata, and tells the reader those rules "cannot fire on a real project and any
finding they produce is wrong."
That inference only holds in one direction. Spring's metadata is authoritative for presence:
a declared key is a real property. It is not authoritative for absence. Boot ships properties
it never declares, and the test currently reports those as invented.
The counterexample is management.endpoint.shutdown.access, which halo sets in its production
configuration and which Boot acts on.
Evidence 1: the key is absent from the index
Replaying the test's own isDeclared() against src/test/resources/spring-metadata/spring-property-index.txt (2920 properties, Boot 2.0.9
through 3.5.16, three artifacts):
isDeclared(management.endpoint.shutdown.access) = False
isDeclared(management.endpoint.heapdump.access) = False
isDeclared(management.endpoints.access.default) = True
Map prefixes that are ancestors of management.endpoint.shutdown.access: []
No Map prefix rescues it, so the test rejects the key outright.
Evidence 2: Boot does not declare it either
The index is not stale or mis-parsed. spring-boot-actuator-autoconfigure 3.5.16 declares 612
properties, of which the entire access family is:
management.endpoint.conditions.access
management.endpoints.access.default
management.endpoints.access.max-permitted
management.endpoint.shutdown.access: ABSENT
management.endpoint.heapdump.access: ABSENT
any name containing 'heapdump': []
This is not new in 3.4. The property access replaced has the same gap. management.endpoint.shutdown.enabled is absent from the index too, and on Boot 2.3.12 adding --management.endpoint.shutdown.enabled=true turned POST /actuator/shutdown from 404 into 200.
Per-endpoint configuration has never been fully declared, in either generation of the property.
Evidence 3: runtime behaviour
Boot 3.5.16, spring-boot-starter-web + spring-boot-starter-actuator, with management.endpoints.web.exposure.include=* in every run. Each row is a separate JVM start,
because a successful POST /actuator/shutdown ends the process and would poison any later
request in the same run:
Extra config
Request
Result
none
POST /actuator/shutdown
404, app alive
management.endpoint.shutdown.access=none
POST /actuator/shutdown
404, app alive
management.endpoint.shutdown.access=unrestricted
POST /actuator/shutdown
200{"message":"Shutting down, bye..."}, process exits
none
GET /actuator/heapdump
404
management.endpoint.heapdump.access=none
GET /actuator/heapdump
404
management.endpoint.heapdump.access=unrestricted
GET /actuator/heapdump
200, ~31 MB, header JAVA PROFILE 1.0.2
Zero unknown-property warnings were logged in any run. That is the same silence that hid the
defects in #39 and #40. Here it means the opposite: the property is real and Boot is acting on it.
Impact
A rule keyed on management.endpoint.shutdown.access is correct and this test rejects it. That
is not hypothetical, it is #45.
The failure text also teaches the wrong lesson to the next contributor. "This key is wrong" and
"I could not confirm this key" call for different responses, and only the second one is
supported by the evidence the test has.
Worth being precise, because the test's wording currently takes credit it has not earned. spring.web.cors.* and spring.security.debug were not condemned by metadata absence alone.
Each was confirmed by runtime observation and by searching the relevant jars for a binding that
never existed. Metadata absence is what pointed at them. It was not the proof.
Proposed fix
Keep the test failing on absence. It is the right default and it earned its place. Fix what the
failure claims:
ConfigKeyMetadataTest javadoc and the everyRuleKeyExistsInSpring failure message: absence
means unconfirmed, not wrong. It is a prompt to verify against the Boot source or a
running app before shipping the key, not a verdict.
Same correction to the "Property keys" bullet in CONTRIBUTING.md, which currently says a
rule keyed on an undeclared property "can never fire".
Document what an ACCEPTED_ABSENCES entry requires: a runtime observation, or a pointer to
the Boot source that binds the property. Without that bar the map is just a mute button, and
the next contributor to hit a red test will reach for it.
Reproducing
$ python3 - <<'EOF'I = "src/test/resources/spring-metadata/spring-property-index.txt"declared, maps = set(), set()for line in open(I, encoding="utf-8"): n = line.strip() if not n or n.startswith("#"): continue if n.endswith("*"): n = n[:-1] maps.add(n) declared.add(n)def is_declared(k): return k in declared or any(k.startswith(p + ".") for p in maps)print(is_declared("management.endpoint.shutdown.access")) # FalseEOF
$ java -jar app.jar --management.endpoints.web.exposure.include='*' \ --management.endpoint.shutdown.access=unrestricted
$ curl -X POST localhost:8080/actuator/shutdown{"message":"Shutting down, bye..."}
Related: #42, which adds the test. This is not an argument against that test, which caught
six invented keys across three rules. It is about what its failure message claims. #45 is
the concrete rule this currently blocks.
Summary
ConfigKeyMetadataTestfails any rule key missing from the vendored index of Spring Boot'sconfiguration metadata, and tells the reader those rules "cannot fire on a real project and any
finding they produce is wrong."
That inference only holds in one direction. Spring's metadata is authoritative for presence:
a declared key is a real property. It is not authoritative for absence. Boot ships properties
it never declares, and the test currently reports those as invented.
The counterexample is
management.endpoint.shutdown.access, which halo sets in its productionconfiguration and which Boot acts on.
Evidence 1: the key is absent from the index
Replaying the test's own
isDeclared()againstsrc/test/resources/spring-metadata/spring-property-index.txt(2920 properties, Boot 2.0.9through 3.5.16, three artifacts):
No Map prefix rescues it, so the test rejects the key outright.
Evidence 2: Boot does not declare it either
The index is not stale or mis-parsed.
spring-boot-actuator-autoconfigure3.5.16 declares 612properties, of which the entire
accessfamily is:This is not new in 3.4. The property
accessreplaced has the same gap.management.endpoint.shutdown.enabledis absent from the index too, and on Boot 2.3.12 adding--management.endpoint.shutdown.enabled=trueturnedPOST /actuator/shutdownfrom 404 into 200.Per-endpoint configuration has never been fully declared, in either generation of the property.
Evidence 3: runtime behaviour
Boot 3.5.16,
spring-boot-starter-web+spring-boot-starter-actuator, withmanagement.endpoints.web.exposure.include=*in every run. Each row is a separate JVM start,because a successful
POST /actuator/shutdownends the process and would poison any laterrequest in the same run:
POST /actuator/shutdownmanagement.endpoint.shutdown.access=nonePOST /actuator/shutdownmanagement.endpoint.shutdown.access=unrestrictedPOST /actuator/shutdown{"message":"Shutting down, bye..."}, process exitsGET /actuator/heapdumpmanagement.endpoint.heapdump.access=noneGET /actuator/heapdumpmanagement.endpoint.heapdump.access=unrestrictedGET /actuator/heapdumpJAVA PROFILE 1.0.2Zero unknown-property warnings were logged in any run. That is the same silence that hid the
defects in #39 and #40. Here it means the opposite: the property is real and Boot is acting on it.
Impact
A rule keyed on
management.endpoint.shutdown.accessis correct and this test rejects it. Thatis not hypothetical, it is #45.
The failure text also teaches the wrong lesson to the next contributor. "This key is wrong" and
"I could not confirm this key" call for different responses, and only the second one is
supported by the evidence the test has.
What #39 and #40 actually rested on
Worth being precise, because the test's wording currently takes credit it has not earned.
spring.web.cors.*andspring.security.debugwere not condemned by metadata absence alone.Each was confirmed by runtime observation and by searching the relevant jars for a binding that
never existed. Metadata absence is what pointed at them. It was not the proof.
Proposed fix
Keep the test failing on absence. It is the right default and it earned its place. Fix what the
failure claims:
ConfigKeyMetadataTestjavadoc and theeveryRuleKeyExistsInSpringfailure message: absencemeans unconfirmed, not wrong. It is a prompt to verify against the Boot source or a
running app before shipping the key, not a verdict.
CONTRIBUTING.md, which currently says arule keyed on an undeclared property "can never fire".
ACCEPTED_ABSENCESentry requires: a runtime observation, or a pointer tothe Boot source that binds the property. Without that bar the map is just a mute button, and
the next contributor to hit a red test will reach for it.
Reproducing
Environment
sprig 0.1.0, at80fd14e(the fix: repoint config rules at property keys Spring actually reads #42 branch)openjdk version "17.0.20" 2026-07-21(Homebrew, build 17.0.20+0)spring-boot-starter-web+spring-boot-starter-actuatorspring-boot-actuator-autoconfigure3.2.12, 3.3.13, 3.4.0, 3.4.1, 3.5.16