Files
document-haness/docs/clean-architecture-backend-template/final/evidence/rendered/a05-f022-stable.svg
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

127 lines
20 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="2108" viewBox="0 0 1200 2108" role="img">
<title>terminal evidence</title>
<desc>Terminal-style rendering generated from retained command output. Sensitive-looking values are redacted in the visual asset.</desc>
<rect x="1" y="1" width="1198" height="2106" rx="14" fill="#0d1117" stroke="#30363d"/>
<rect x="1" y="1" width="1198" height="44" rx="14" fill="#161b22"/>
<rect x="1" y="30" width="1198" height="14" fill="#161b22"/>
<circle cx="24" cy="22" r="6" fill="#ff5f57"/>
<circle cx="44" cy="22" r="6" fill="#febc2e"/>
<circle cx="64" cy="22" r="6" fill="#28c840"/>
<text x="92" y="27" fill="#8b949e" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace">terminal evidence</text>
<text x="24" y="68" fill="#c9d1d9" font-size="15" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">$ V=adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/security/PostgreSqlRuntim</tspan><tspan x="24" dy="22">eRoleVerifier.java
D=adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/security</tspan><tspan x="24" dy="22">/DatabaseRolePolicy.java
R=app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaPlatformReport.java</tspan><tspan x="24" dy="22">
A=app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaPlatformAutoConfiguration.java
C=adapter/ou</tspan><tspan x="24" dy="22">tbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/api/capability/SupportLevel.java
echo </tspan><tspan x="24" dy="22">&#x27;# 검증기 자신의 javadoc 이 하는 주장&#x27;
grep -n &#x27;&#x27; &quot;$V&quot; | sed -n &#x27;18,19p&#x27;
echo
echo &#x27;# 정책이 검사하는 네 항목&#x27;
grep -n </tspan><tspan x="24" dy="22">&#x27;allowedRoles.contains\|report.canCreateInSchema()\|report.canCreateInDatabase()\|searchPathPolicy.requireSafe&#x27; &quot;$D&quot;
ec</tspan><tspan x="24" dy="22">ho
echo &#x27;# 검증기는 프로덕션에서 실제로 불린다 — 다만 기동이 아니라 리포트를 만들 때다&#x27;
grep -n -A5 &#x27;private DatabasePr</tspan><tspan x="24" dy="22">ivilegeReport readPrivileges&#x27; &quot;$A&quot;
grep -n &#x27;roleVerifier.verify(dataSource)&#x27; &quot;$A&quot;
echo
echo &#x27;# 정책을 넘기는 두 인자짜</tspan><tspan x="24" dy="22">리 호출&#x27;
grep -n -A3 &#x27;public void requireSafe(DataSource dataSource&#x27; &quot;$V&quot;
echo -n &#x27;# 그 호출을 하는 곳 (레포 전체): &#x27;
</tspan><tspan x="24" dy="22">grep -rn &#x27;requireSafe([a-zA-Z]*, *[a-zA-Z]*)&#x27; --include=*.java --exclude-dir=build . | grep -c &#x27;requireSafe(runtime\|req</tspan><tspan x="24" dy="22">uireSafe(dataSource&#x27;
grep -rn &#x27;\.requireSafe([a-zA-Z]*, *[a-zA-Z]*)&#x27; --include=*.java --exclude-dir=build . | sed &#x27;s|^\.</tspan><tspan x="24" dy="22">/||&#x27;
echo -n &#x27;# DatabaseRolePolicy 를 만드는 main 코드: &#x27;
grep -rn &#x27;new DatabaseRolePolicy\|DatabaseRolePolicy\.of&#x27; --</tspan><tspan x="24" dy="22">include=*.java --exclude-dir=build . | grep -c &#x27;/main/&#x27;
echo -n &#x27;# DatabaseRolePolicy 를 언급하는 파일 전부: &#x27;
grep -r</tspan><tspan x="24" dy="22">l &#x27;DatabaseRolePolicy&#x27; --include=*.java --exclude-dir=build . | sed &#x27;s|.*/||&#x27; | tr &#x27;\n&#x27; &#x27; &#x27;; echo
echo
echo &#x27;# 기동 검</tspan><tspan x="24" dy="22">사 빈이 실행하는 것&#x27;
grep -n -A6 &#x27;InitializingBean jpaPlatformStartupCheck&#x27; &quot;$A&quot; 2&gt;/dev/null || \
grep -n -A6 &#x27;Initial</tspan><tspan x="24" dy="22">izingBean jpaPlatformStartupCheck&#x27; app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/jpa/JpaPlatformRun</tspan><tspan x="24" dy="22">timeAutoConfiguration.java
echo
echo &#x27;# 액추에이터의 검증 완료 표시가 보는 것&#x27;
grep -n &#x27;&#x27; &quot;$R&quot; | sed -n &#x27;36,41p&#x27;
grep -</tspan><tspan x="24" dy="22">n &#x27;privileges != null&#x27; &quot;$R&quot;
grep -n &#x27;openInViewDisabled &amp;&amp; runtimeRoleVerified&#x27; &quot;$R&quot;
echo
echo &#x27;# 그 표시를 고정하는 시</tspan><tspan x="24" dy="22">험이 넣는 입력&#x27;
grep -n &#x27;new DatabasePrivilegeReport&#x27; app-bootstrap/src/test/java/dev/caskeleton/bootstrap/autoconfigure</tspan><tspan x="24" dy="22">/jpa/JpaPlatformAutoConfigurationTest.java
echo &#x27;# 정책 쪽 단위 시험은 그 두 조합을 실제로 넣는다&#x27;
grep -n &#x27;new Databa</tspan><tspan x="24" dy="22">sePrivilegeReport&#x27; adapter/outbound/persistence-jpa/src/test/java/dev/caskeleton/adapter/outbound/persistence/security/D</tspan><tspan x="24" dy="22">atabaseRolePolicyTest.java
echo
echo &#x27;# 안정 등급의 정의&#x27;
grep -n -B2 &#x27; STABLE,&#x27; &quot;$C&quot;</tspan></text>
<text x="24" y="574" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">cwd: /shared/codebase/clean-architecture-backend-template/src</tspan></text>
<text x="24" y="596" fill="#8b949e" font-size="13" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">time: 2026-09-02T04:41:19+00:00 · exit 0</tspan></text>
<line x1="24" y1="610" x2="1176" y2="610" stroke="#30363d"/>
<text x="24" y="650" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 검증기 자신의 javadoc 이 하는 주장</tspan></text>
<text x="24" y="672" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">18: * &lt;p&gt;The verification runs at startup and fails closed. Discovering after an incident that the</tspan></text>
<text x="24" y="694" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">19: * application&#x27;s own credential could drop tables is discovering it too late.</tspan></text>
<text x="24" y="716" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="738" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 정책이 검사하는 네 항목</tspan></text>
<text x="24" y="760" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">40: if (!allowedRoles.contains(currentUser)) {</tspan></text>
<text x="24" y="782" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">44: if (report.canCreateInSchema()) {</tspan></text>
<text x="24" y="804" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">51: if (report.canCreateInDatabase()) {</tspan></text>
<text x="24" y="826" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">55: searchPathPolicy.requireSafe(report.searchPath());</tspan></text>
<text x="24" y="848" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="870" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 검증기는 프로덕션에서 실제로 불린다 — 다만 기동이 아니라 리포트를 만들 때다</tspan></text>
<text x="24" y="892" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">110: private DatabasePrivilegeReport readPrivileges(DataSource dataSource) {</tspan></text>
<text x="24" y="914" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">111- try {</tspan></text>
<text x="24" y="936" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">112- return roleVerifier.verify(dataSource);</tspan></text>
<text x="24" y="958" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">113- } catch (IllegalStateException unverified) {</tspan></text>
<text x="24" y="980" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">114- return null;</tspan></text>
<text x="24" y="1002" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">115- }</tspan></text>
<text x="24" y="1024" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">112: return roleVerifier.verify(dataSource);</tspan></text>
<text x="24" y="1046" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1068" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 정책을 넘기는 두 인자짜리 호출</tspan></text>
<text x="24" y="1090" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">55: public void requireSafe(DataSource dataSource, DatabaseRolePolicy policy) {</tspan></text>
<text x="24" y="1112" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">56- Objects.requireNonNull(policy, &quot;policy&quot;);</tspan></text>
<text x="24" y="1134" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">57- policy.requireSafe(verify(dataSource));</tspan></text>
<text x="24" y="1156" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">58- }</tspan></text>
<text x="24" y="1178" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 그 호출을 하는 곳 (레포 전체): 1</tspan></text>
<text x="24" y="1200" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/platform/Postgre</tspan><tspan x="24" dy="22">SqlSecurityContractTest.java:92: new PostgreSqlRuntimeRoleVerifier().requireSafe(runtime, policy);</tspan></text>
<text x="24" y="1244" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># DatabaseRolePolicy 를 만드는 main 코드: 0</tspan></text>
<text x="24" y="1266" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># DatabaseRolePolicy 를 언급하는 파일 전부: PostgreSqlSecurityContractTest.java DatabaseRolePolicyTest.java PostgreSqlRuntimeR</tspan><tspan x="24" dy="22">oleVerifier.java DatabaseRolePolicy.java </tspan></text>
<text x="24" y="1310" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1332" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 기동 검사 빈이 실행하는 것</tspan></text>
<text x="24" y="1354" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">194: public InitializingBean jpaPlatformStartupCheck(</tspan></text>
<text x="24" y="1376" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">195- JpaDangerousConfigurationGuard guard, Environment environment) {</tspan></text>
<text x="24" y="1398" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">196- // A refresh-time failure beats a runtime one: OSIV left on, or a schema-mutating ddl-auto in a</tspan></text>
<text x="24" y="1420" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">197- // profile that forbids it, is a deployment mistake and not a request-time condition.</tspan></text>
<text x="24" y="1442" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">198- return () -&gt; guard.validate(environment);</tspan></text>
<text x="24" y="1464" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">199- }</tspan></text>
<text x="24" y="1486" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">200-</tspan></text>
<text x="24" y="1508" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1530" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 액추에이터의 검증 완료 표시가 보는 것</tspan></text>
<text x="24" y="1552" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">36: * Builds the report, deriving only bounded values from the privilege report.</tspan></text>
<text x="24" y="1574" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">37: *</tspan></text>
<text x="24" y="1596" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">38: * &lt;p&gt;The privilege report&#x27;s {@code currentUser} and {@code searchPath} are deliberately reduced</tspan></text>
<text x="24" y="1618" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">39: * to a single boolean here: an operator needs to know the runtime role passed verification, not</tspan></text>
<text x="24" y="1640" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">40: * which role it is.</tspan></text>
<text x="24" y="1662" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">41: */</tspan></text>
<text x="24" y="1684" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">56: privileges != null &amp;&amp; !privileges.holdsCreatePrivilege(),</tspan></text>
<text x="24" y="1706" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">62: return openInViewDisabled &amp;&amp; runtimeRoleVerified;</tspan></text>
<text x="24" y="1728" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1750" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 그 표시를 고정하는 시험이 넣는 입력</tspan></text>
<text x="24" y="1772" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">37: new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app, pg_catalog&quot;, false, false),</tspan></text>
<text x="24" y="1794" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">58: new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app&quot;, true, false),</tspan></text>
<text x="24" y="1816" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 정책 쪽 단위 시험은 그 두 조합을 실제로 넣는다</tspan></text>
<text x="24" y="1838" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">21: policy.requireSafe(new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app, pg_catalog&quot;, false, false));</tspan></text>
<text x="24" y="1860" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">29: policy.requireSafe(new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app&quot;, true, false)))</tspan></text>
<text x="24" y="1882" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">38: () -&gt; policy.requireSafe(new DatabasePrivilegeReport(&quot;postgres&quot;, &quot;app&quot;, false, false)))</tspan></text>
<text x="24" y="1904" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">49: new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app, public&quot;, false, false)))</tspan></text>
<text x="24" y="1926" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">57: policy.requireSafe(new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;\&quot;$user\&quot;, app&quot;, false, false));</tspan></text>
<text x="24" y="1948" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">58: assertThat(policy.isSafe(new DatabasePrivilegeReport(&quot;app_runtime&quot;, &quot;app&quot;, false, false)))</tspan></text>
<text x="24" y="1970" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"></tspan></text>
<text x="24" y="1992" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0"># 안정 등급의 정의</tspan></text>
<text x="24" y="2014" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">10-</tspan></text>
<text x="24" y="2036" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">11- /** Verified by the Stable contract suite on the whole PostgreSQL Stable matrix. */</tspan></text>
<text x="24" y="2058" fill="#e6edf3" font-size="14" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" xml:space="preserve"><tspan x="24" dy="0">12: STABLE,</tspan></text>
</svg>