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>
50 lines
3.6 KiB
Plaintext
50 lines
3.6 KiB
Plaintext
# 재시도 정책이 보는 두 값은 어디서 오는가
|
|
372: profile.capabilities().providerIdempotency(),
|
|
373: profile.capabilities().statusQuery(),
|
|
55: if (context.statusQuerySupported()) {
|
|
58: if (!context.providerIdempotency()) {
|
|
|
|
# 알림 경로에서 capabilities 를 선언하고 부르는 자리 — 수신자가 무엇인지 본다
|
|
main · SmtpProviderRuntimeAssembler.java:136: capabilities(),
|
|
main · SmtpProviderRuntimeAssembler.java:148: private static ProviderCapabilities capabilities() {
|
|
main · SesNotificationProviderAdapter.java:86: public ProviderCapabilities capabilities() {
|
|
main · WebPushNotificationProviderAdapter.java:64: public ProviderCapabilities capabilities() {
|
|
main · SmtpNotificationProviderAdapter.java:72: public ProviderCapabilities capabilities() {
|
|
main · TwilioSmsProviderAdapter.java:68: public ProviderCapabilities capabilities() {
|
|
main · TwilioReconciliationCapability.java:58: return profile.capabilities().statusQuery();
|
|
main · FcmNotificationProviderAdapter.java:45: public ProviderCapabilities capabilities() {
|
|
main · ApnsNotificationProviderAdapter.java:68: public ProviderCapabilities capabilities() {
|
|
main · WebhookNotificationProviderAdapter.java:91: public ProviderCapabilities capabilities() {
|
|
main · NotificationDispatchService.java:269: if (!profile.capabilities().collapse()) {
|
|
main · NotificationDispatchService.java:372: profile.capabilities().providerIdempotency(),
|
|
main · NotificationDispatchService.java:373: profile.capabilities().statusQuery(),
|
|
main · NotificationProviderAdapter.java:23: ProviderCapabilities capabilities();
|
|
|
|
# ProviderProfileSnapshot 을 만드는 자리
|
|
test · NotificationObservationTest.java:315: new ProviderProfileSnapshot(
|
|
test · ProviderRuntimeStateTest.java:201: new ProviderProfileSnapshot(
|
|
test · ProviderRuntimeRegistryConcurrencyTest.java:154: new ProviderProfileSnapshot(
|
|
test · ProviderRuntimeRegistryTest.java:134: new ProviderProfileSnapshot(
|
|
test · NotificationProviderAssemblyTest.java:249: new ProviderProfileSnapshot(
|
|
test · ProviderFixtures.java:47: return new ProviderProfileSnapshot(
|
|
main · SmtpProviderRuntimeAssembler.java:127: return new ProviderProfileSnapshot(
|
|
|
|
# ProviderRuntimeAssembler 구현
|
|
test · NotificationLegacyNamespaceRetirementTest.java:70: .filter(path -> read(path).contains("implements ProviderRuntimeAssembler"))
|
|
main · SmtpProviderRuntimeAssembler.java:48:public final class SmtpProviderRuntimeAssembler implements ProviderRuntimeAssembler {
|
|
|
|
# 문제의 세 어댑터를 생성하는 자리
|
|
test · SesNotificationProviderAdapterTest.java:259: return new SesNotificationProviderAdapter(
|
|
test · WebPushProviderAdapterTest.java:139: return new WebPushNotificationProviderAdapter(
|
|
test · TwilioSmsProviderAdapterTest.java:49: return new TwilioSmsProviderAdapter(
|
|
test · ContractAdapters.java:108: new SesNotificationProviderAdapter(
|
|
test · ContractAdapters.java:148: new TwilioSmsProviderAdapter(
|
|
test · ContractAdapters.java:199: new WebPushNotificationProviderAdapter(
|
|
|
|
# 조립기가 없는 계열을 만나면 기동이 거부된다
|
|
main · NotificationProviderAssembly.java-98- "notification provider profile '"
|
|
main · NotificationProviderAssembly.java-99- + profileId
|
|
main · NotificationProviderAssembly.java-100- + "' is of type "
|
|
main · NotificationProviderAssembly.java-101- + type
|
|
main · NotificationProviderAssembly.java:102: + ", which has no assembler in this build. The transport is a seam, not an"
|