# 능력 선언 — 제약을 평범한 문자열로만 담는 이유 *
Constraints are plain bounded strings on purpose. A capability record must stay serialisable
* into a report and safe to publish through an actuator endpoint, so it never stores a provider
* object — no {@code DataSource}, no {@code EntityManagerFactory}, no Hibernate {@code
* SessionFactory}. Holding one would drag a live resource into a value type and let a report leak a
* JDBC URL or credentials.
*/
public record CapabilitySupport(
JpaCapability capability, SupportLevel level, List Deliberately narrow: the connected role, the schema search path, and two privilege answers.
* There is no JDBC URL, no password, and no host — this record is designed to be safe to surface in
* an actuator endpoint, and anything that would have to be masked before publishing does not belong
* in it at all.
*/
public record DatabasePrivilegeReport(
String currentUser, String searchPath, boolean canCreateInSchema, boolean canCreateInDatabase) {
# 밖으로 나가는 리포트 — 담을 수 없는 것
/**
* What the JPA platform is willing to say about itself over HTTP (design §37).
*
* The interesting part of this type is what it cannot hold. There is no JDBC URL, no username,
* no password, no SQL, and no entity catalog — an actuator endpoint is reachable by anyone who
* reaches the management port, and every one of those would be a free reconnaissance answer.
*
* What it does report is what an operator actually needs during an incident: which database
* major version is behind this instance, which provider, which schema version, and whether the
* safety properties this platform depends on are holding.
# 그 리포트가 특권 리포트를 담는 방식과, 그 불리언이 실제로 계산하는 것
/**
* Builds the report, deriving only bounded values from the privilege report.
*
* The privilege report's {@code currentUser} and {@code searchPath} are deliberately reduced
* to a single boolean here: an operator needs to know the runtime role passed verification, not
* which role it is.
openInViewDisabled,
privileges != null && !privileges.holdsCreatePrivilege(),
capabilities);
# 역할 이름과 search_path 를 검사하는 정책의 main 호출자: 0
# 두 리포트의 컴포넌트 선언부에 있는 provider/자격증명 식별자 수
JpaPlatformReport.java: 0
DatabasePrivilegeReport.java: 0
# 그 리포트를 내보내는 엔드포인트
20:@Endpoint(id = "jpaplatform")
30: @ReadOperation
@WriteOperation / @DeleteOperation / @Selector 매치: 0
*
* Read-only by construction: there is no write operation and no parameter. An endpoint that
* could trigger a migration, a repair, or a cache eviction would be an admin capability reachable
* over HTTP by whoever reaches the management port, which is exactly the boundary design §8.4 puts
* those operations behind.
# 다만 그 엔드포인트는 지금 노출되지 않는다
저장소에서 'jpaplatform' 이 나오는 곳: 1
JpaPlatformEndpoint.java:20:@Endpoint(id = "jpaplatform")
출하 설정의 노출 목록
258: include: health,prometheus,info,loggers,adapteractivation
259- # D2/D4/D5: explicitly excluded dangerous endpoints (env leaks secrets,
260- # heapdump/threaddump = memory forensics, shutdown = remote kill, configprops = secret leak).
등록 지점이 그것을 적어 둔다
*
* {@code @Endpoint} alone registers nothing; exposure is still governed by the application's
* existing {@code management.endpoints} policy, which this deliberately does not widen.