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>
139 KiB
Source Index
상세 문서의 주장과 근거를 다시 찾을 수 있게 code/config/test/git/runtime source를 색인한다.
| id | kind | path / command / URL | revision or time | what it proves | limitations |
|---|---|---|---|---|---|
| SRC-001 | git | evidence/raw/001-git-snapshot.txt |
a24ece9cf797f7ea647e33bf846b115208ed1ba5 |
분석 snapshot과 clean branch 상태 | 이후 source 변경에는 적용 안 됨 |
| SRC-002 | registry/inventory | src/config/architecture/modules.json, evidence/raw/002-module-inventory.txt |
same revision | 44 registered leaves, dependency/runtime memberships, initial file/LOC sizing | initial sizing은 각 bounded scope final denominator와 다를 수 있음 |
| SRC-003 | module policy | src/domain-core/CLAUDE.md |
same revision | domain-core responsibility/allowed/forbidden/test contract | policy 문서; 실제 enforcement는 별도 확인 필요 |
| SRC-004 | rationale | src/domain-core/README.md |
same revision | ResourceId unsealed, marker/guardrail rationale | 문서 claim은 code/test와 교차검증해야 함 |
| SRC-005 | code | src/domain-core/src/main/java/dev/caskeleton/domain/identifier/ResourceId.java |
same revision | self-typed ID interface와 value() surface |
UUIDv7 validation 구현 없음 |
| SRC-006 | code | src/domain-core/src/main/java/dev/caskeleton/domain/identifier/IdFactory.java |
same revision | identifier generation port | concrete uniqueness/generation semantics는 adapter 책임 |
| SRC-007 | code | src/domain-core/src/main/java/dev/caskeleton/domain/stereotype/*.java |
same revision | runtime-retained framework-neutral markers | marker 자체가 invariant를 구현하지 않음 |
| SRC-008 | build | src/domain-core/build.gradle |
same revision | explicit module dependency block empty | convention plugin/tool dependencies는 root/build-logic에서 올 수 있음 |
| SRC-009 | build policy | src/build-logic/.../ModuleRegistry.groovy, ca.architecture-registry.settings.gradle |
same revision | registry fail-closed validation과 project inclusion | runtime behavior 자체는 아님 |
| SRC-010 | build verification | src/build.gradle:1401+ verifyCleanArchitectureDependencies |
same revision | actual project dependency edge와 allowlist 비교 | non-project external dependencies는 이 task 범위 밖 |
| SRC-011 | architecture test | src/app-bootstrap/.../CleanArchitectureTest.java domain rules |
same revision | purity/value-object/aggregate/event/ResourceId enforcement | 전체 2,792라인 중 관련 rule만 bounded scope에서 해석 |
| SRC-012 | consumer code | src/sample-portfolio/.../WorkLogId.java, WorkLogIdFactory.java, UuidWorkLogIdFactory.java |
same revision | ResourceId/IdFactory concrete reachability | sample implementation이지 모든 consumer를 대표하지 않음 |
| SRC-013 | consumer code | src/sample-portfolio/.../WorkLog.java, WorkLogReserved.java |
same revision | AggregateRoot/DomainEvent production use | sample domain 전체 분석은 아님 |
| SRC-014 | test | src/sample-portfolio/.../WorkLogIdPropertyTest.java |
same revision | canonical shape를 허용/비-shape를 거부 | UUID version/variant는 검증하지 않음 |
| SRC-015 | test | src/sample-portfolio/.../UuidWorkLogIdFactoryTest.java |
same revision | factory canonical output/distinctness/monotonicity | global uniqueness proof 아님 |
| SRC-016 | runtime consumer | src/adapter/inbound/websocket/.../LiveEventStompBroadcaster.java |
same revision | DomainEvent RUNTIME retention의 production reflection consumer 존재 |
broadcaster 전체 behavior는 websocket scope 대상 |
| EVD-001 | command | evidence/raw/003-domain-core-test.txt |
2026-08-29 | :domain-core:test build task 실행 결과 |
module 자체 Java test 0개 |
| EVD-002 | command | evidence/raw/004-clean-architecture-test.txt |
2026-08-29 | cross-module architecture test가 BUILD SUCCESSFUL / exit code 0 | 이 실행은 현재 snapshot의 전체 ArchUnit suite 결과이며 개별 rule의 미래 변경까지 보장하지 않음 |
| SRC-017 | module policy/rationale/build | src/shared-contract/CLAUDE.md, README.md, build.gradle |
same revision | stdlib-only boundary, responsibilities, custom qualification lanes | policy/rationale claims are cross-checked against code/tests |
| SRC-018 | code/resource | src/shared-contract/src/main/** |
same revision | shared error/response/rate-limit/metrics/tracing/concurrency/opstore/activation/health contracts and messaging schema | downstream adapter behavior belongs to their bounded scopes |
| SRC-019 | tests | src/shared-contract/src/test/**, src/edgeRateLimitContractTest/** |
same revision | constructor/factory invariants, vocabulary, resource digest and provider-neutral rate-limit contract | does not prove external JSON Schema validator interoperability |
| SRC-020 | reachability | production references to DomainContextPropagator and OperationalRecordStorePort |
same revision | actual app-bootstrap/JPA/sample/GraphQL consumers exist | representative reachability, not exhaustive consumer analysis |
| EVD-005 | command | evidence/raw/005-shared-contract-test.txt |
2026-08-29 | :shared-contract:test BUILD SUCCESSFUL / exit 0 |
focused module test only |
| EVD-006 | command | evidence/raw/006-shared-contract-edge-rate-limit-test.txt |
2026-08-29 | strict edgeRateLimitContractTest BUILD SUCCESSFUL / exit 0 |
provider-neutral contract lane only |
| SRC-021 | code/tests | src/application-core/src/main/java/dev/caskeleton/application/{usecase,command,query,capability}/**, matching src/test/** |
same revision | framework-free use-case type split and runtime-readable capability declaration surface | mandatory/coherence enforcement still requires architecture-rule trace |
| SRC-022 | transaction code/tests | src/application-core/src/main/java/dev/caskeleton/application/transaction/{TransactionMode,TransactionPort,PolicyTransactionPort,TransactionRequest}.java, TransactionPortTest.java, TransactionRequestTest.java |
same revision | transaction mode surface, root-write abstract contract, runnable delegation, request coherence validation | remaining transaction package and concrete adapter semantics not yet fully read |
| SRC-023 | security code/tests | src/application-core/src/main/java/dev/caskeleton/application/security/**, AuthorizationContractTest.java, ObjectAccessPolicyTest.java |
same revision | framework-neutral permission/object-access contracts, invariants, transport-neutrality regression history | actual web interception/translation and production policy implementation belong to consumer traces |
| SRC-024 | transaction code/tests | src/application-core/src/main/java/dev/caskeleton/application/transaction/**, matching src/test/** |
same revision | full application transaction vocabulary, policy request/result algebra, reconciliation and retry-safety contracts | framework execution semantics require adapter trace |
| SRC-025 | adapter code/test | src/adapter/outbound/persistence-jpa/.../transaction/SpringTransactionPort.java, SpringTransactionPortTest.java |
same revision | REQUIRED/REQUIRES_NEW mapping, explicit READ_COMMITTED, root ambient rejection, commit-before-return and commit-failure behavior | focused fake transaction manager; broader policy executor belongs persistence-jpa scope |
| SRC-026 | architecture test | src/app-bootstrap/.../CleanArchitectureTest.java capability/repository/transaction/auth rules |
same revision | mandatory UseCaseCapability, direct transaction/repository coherence, mutating permission declaration, Spring Security dependency ban | direct-call static analysis has documented helper/AOP blind spots |
| EVD-007 | command | ./gradlew :application-core:test |
2026-08-29 | application-core tests BUILD SUCCESSFUL | module tests do not alone prove adapter/runtime semantics |
| EVD-008 | command | ./gradlew :app-bootstrap:test --tests dev.caskeleton.bootstrap.architecture.CleanArchitectureTest |
2026-08-29 | architecture test task resolved BUILD SUCCESSFUL | Gradle reported task UP-TO-DATE; verifies current cached inputs/output state rather than fresh test execution |
| SRC-027 | application reliability code/tests | src/application-core/src/main/java/dev/caskeleton/application/{idempotency,inbox,outbox,operation}/**, matching src/test/** |
same revision | owner-safe idempotency/inbox/outbox/durable-operation state, uncertainty and retry/reconciliation semantics | concrete persistence/provider implementation details belong to later scopes |
| SRC-028 | cache/coordination code/tests | src/application-core/src/main/java/dev/caskeleton/application/{cache,lease,lock,outbound,observability}/**, matching src/test/** |
same revision | cache-aside race control, bounded single-flight/bulkhead, efficiency-only lease/lock contracts, low-cardinality outbound/observation semantics | actual Redis/JDBC provider failure behavior belongs to adapter scopes |
| SRC-029 | messaging/realtime code/tests | src/application-core/src/main/java/dev/caskeleton/application/{messaging,realtime}/**, matching messaging tests |
same revision | provider/transport-neutral messaging catalog/event envelope and realtime durability/replay/presence contracts | full broker/websocket runtime behavior is cross-scope |
| SRC-030 | storage/publication code/tests | src/application-core/src/main/java/dev/caskeleton/application/{storage,fileexport,filepublication}/**, matching tests |
same revision | legacy raw-storage compatibility path versus semantic publication contracts and CSV safety rules | legacy removal completion not established |
| SRC-031 | objectstorage code/tests | src/application-core/src/main/java/dev/caskeleton/application/objectstorage/**, matching tests |
same revision | opaque identities, bounded content streaming, staged verification/publish, fencing, grants and privilege separation | concrete provider implementation is later outbound objectstorage scope |
| SRC-032 | fileserver code/tests | src/application-core/src/main/java/dev/caskeleton/application/fileserver/**, matching tests |
same revision | upload/download lifecycle, writer fencing, cleanup/recovery, quota, HTTP/range/content-safety and physical/metadata ambiguity handling | concrete fileserver adapter/runtime workers are cross-scope |
| SRC-033 | notification code/tests | src/application-core/src/main/java/dev/caskeleton/application/notification/**, matching tests |
same revision | typed public API, protected contacts, routing, dispatch uncertainty, callbacks, provider evidence, admin/operator contracts | concrete adapters/provider SDK semantics are later scopes |
| SRC-034 | reachability | evidence/raw/013-application-core-reachability.txt, evidence/raw/013-application-core-reachability-command.sh |
2026-08-29 | external production reference files for major application packages, distinguishing active/legacy/unwired paths | static references prove reachability, not that every referenced code path executes in every deployment |
| SRC-035 | build | src/application-core/build.gradle, root src/build.gradle messaging evidence/qualification configuration |
same revision | shared-contract-only production dependency, strict messaging qualification required classes and fail-closed evidence properties | build policy does not itself prove runtime behavior |
| SRC-036 | defect trace | AdminOperationStorePort.java, NotificationAdminApplicationService.java, JpaAdminOperationStore.java |
same revision | atomic admin claim contract and adapter implementation exist, while application service still uses find-before-effect/save and never calls claim | concurrency impact is statically demonstrated by control flow/history; dedicated reproducer remains backlog |
| EVD-009 | command | evidence/raw/009-application-core-test.txt |
2026-08-29 | fresh :application-core:test --rerun-tasks BUILD SUCCESSFUL |
application-core test lane does not replace provider integration tests |
| EVD-010 | command | evidence/raw/010-application-core-messaging-qualification.txt, 010a-messaging-qualification-missing-attestation.txt, 014-application-core-verification-metadata.txt |
2026-08-29 | strict messaging application qualification: missing attestation fails closed; exact digest rerun passes 15 tests with 0 skipped | digests identify this analysis invocation, not a broader release attestation |
| EVD-011 | command | evidence/raw/011-clean-architecture-test.txt |
2026-08-29 | fresh CleanArchitectureTest rerun BUILD SUCCESSFUL, 98 actionable tasks executed | static architecture tests retain documented indirect-call/reflection/AOP blind spots |
| EVD-012 | command | evidence/raw/012-verify-clean-architecture-dependencies.txt |
2026-08-29 | verifyCleanArchitectureDependencies BUILD SUCCESSFUL |
validates project dependency registry edges, not arbitrary runtime calls |
| SRC-037 | module code/test/build/docs | src/adapter/outbound/support/{src/**,build.gradle,README.md,CLAUDE.md} |
same revision | complete leaf-owned surface: MDC correlation lookup, shared fail-open dependency logger, default Spring bean seam, focused test and local design claims | downstream adapter behavior and full app runtime are outside the leaf denominator and require separate consumer/composition evidence |
| SRC-038 | registry/composition/architecture | src/config/architecture/modules.json, src/app-bootstrap/.../CaSkeletonApplication.java, CleanArchitectureTest.java, src/app-bootstrap/build.gradle |
same revision | support runtime membership, broad component-scan reachability, direct app-bootstrap dependency, and outbound-peer rule allowing shared dependency into support | source/ArchUnit wiring does not prove every deployment creates or exercises every consumer path |
| SRC-039 | consumer code/tests | OutboundMessagePublisher.java, FailOpenNotificationProvider.java, OutboundMessagePublisherTest.java, NotificationAdapterTest.java, OptionalAdapterBeanGatingTest.java |
same revision | actual messaging/notification use of the shared logger, messaging diagnostic-failure isolation regression, current notification test coverage, and optional-adapter gating harness | only the support-relevant consumer paths were read; messaging/notification modules are not exhaustively analyzed in this scope |
| SRC-040 | logging/privacy contracts | application-core/.../Notification.java, notification provider/client SPIs, app-bootstrap/.../LogMaskingPatterns.java, relevant app-bootstrap README logging section, docs/registries/mdc-keys.yaml |
same revision | Notification recipient/body PII contract, unrestricted exception surfaces, current secret-masking vocabulary, and correlation-id registry ownership | does not establish the exception text behavior of every external SDK or every production log backend |
| SRC-041 | git/document history | git log -S'OutboundHttpDependencyLogger', support README history |
same revision | historical HTTP dependency logger existed and was later deleted while the support README comparison text remained | history establishes repository evolution, not the motivation behind every deletion unless explicitly recorded in commit/source text |
| EVD-013 | static probes | evidence/raw/015-adapter-outbound-support-inventory.txt through 020-adapter-outbound-support-project-edge-usage.txt |
2026-08-29 | quantified leaf inventory plus required public-reachability, conditional-wiring, duplicate-mechanism, documentation-drift and project-edge-usage searches | textual/static probes do not cover reflection, generated registration, external consumers, or runtime execution unless separately evidenced |
| EVD-014 | runtime probe | evidence/raw/021a-support-logger-pii-probe.java, 021-support-logger-pii-probe.txt |
2026-08-29 | current compiled FailOpenDependencyLogger renders explicit email/body markers present in an exception message into the WARN message | controlled local probe proves logger behavior for supplied exception text; it does not claim a particular real provider currently emits that exact text |
| EVD-015 | runtime probe | evidence/raw/022a-notification-logger-failure-probe.java, 022-notification-logger-failure-probe.txt |
2026-08-29 | current compiled notification consumer calls failure observation after a successful send when success logging throws, and propagates a failure-logging RuntimeException | uses a deliberately throwing SLF4J proxy rather than a real disk-full/appender outage; it isolates the control-flow contract |
| EVD-016 | command | evidence/raw/023-adapter-outbound-support-test.txt |
2026-08-29 | fresh :adapter:outbound:support:test --rerun-tasks execution succeeds |
focused leaf test does not exercise exception-message PII or throwing-logger consumer behavior |
| EVD-017 | command | evidence/raw/024-adapter-outbound-support-dependencies.txt, 025-clean-architecture-dependencies.txt |
2026-08-29 | current support compileClasspath has external Spring/SLF4J dependencies and registry project-edge verification succeeds | dependency verification proves allowed graph shape, not semantic necessity of every consumer edge |
| EVD-018 | command | evidence/raw/026-messaging-support-consumer-test.txt, 027-notification-support-consumer-test.txt, 028-optional-adapter-bean-gating-test.txt |
2026-08-29 | fresh relevant messaging, notification and optional-adapter composition test classes succeed | selected focused tests do not substitute for exhaustive downstream-module or full deployed-runtime testing |
| EVD-019 | command | evidence/raw/029-clean-architecture-support-rule.txt |
2026-08-29 | fresh CleanArchitectureTest execution succeeds with the outbound-peer/support exception rule present | ArchUnit statically verifies bytecode dependency rules; it does not prove runtime activation or logging failure behavior |
| SRC-042 | JPA API code/tests | src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/api/**, matching src/test/**/api/** |
same revision | complete 49-type external API vocabulary plus 6 dedicated tests: bounded operation/query identities, failure algebra, cursor/keyset contracts, transaction/retry/completion evidence | implementation semantics such as actual commit classification, SQLSTATE translation and query observation are owned by later sub-scopes |
| SRC-043 | JPA API consumers/wiring | src/app-bootstrap/.../jpa/{JpaPlatformAutoConfiguration,JpaPlatformReport,JpaPlatformEndpoint,JpaPlatformRuntimeAutoConfiguration}.java, persistence JpaRetryObservation, DefaultJpaRetryPolicy, FullTransactionRetryCoordinator |
same revision | capability report reaches actuator model, retry reason is not a current metric tag, and API transaction types feed actual retry coordinator | consumer reads are API-meaning traces only; their owning implementation sub-scopes are not thereby complete |
| SRC-044 | JPA API surface/history | docs/architecture/jpa-api-surface.txt, src/build-logic/.../ca.api-surface.gradle, git history for SignedJsonCursorCodec, CapabilitySupport, JpaEntityNotFoundException |
same revision | committed 49-type intended external API surface and history of cursor bound hardening | public-surface baseline governs names, not method behavior or external adopter usage |
| EVD-020 | static probes | evidence/raw/031-persistence-jpa-module-inventory.txt through 034-persistence-jpa-api-document-surface-check.txt |
2026-08-29 | 605-file module denominator and API public-reachability/conditional/duplicate/document-surface probes | static/textual reachability excludes reflection/generated code/external adopters and can over-count same-package Javadoc references |
| EVD-021 | runtime probe | evidence/raw/035a-jpa-cursor-boundary-probe.java, 035-jpa-cursor-boundary-probe.txt |
2026-08-29 | current compiled cursor codec round-trips 2045 bytes but rejects its own encoded tokens at 2046–2048 bytes while rejecting 2049 at encode | focused codec probe does not exercise HTTP transport or an application-specific cursor payload mapper |
| EVD-022 | runtime probe | evidence/raw/036a-jpa-api-bound-probe.java, 036-jpa-api-bound-probe.txt |
2026-08-29 | constructors accept 100k-character capability constraints/retry reason and Integer.MAX_VALUE maxAttempts |
records type-level bounds only; current shipped composition does not supply such capability strings and effective retry budget needs transaction trace |
| EVD-023 | command | evidence/raw/037-persistence-jpa-api-tests.txt, 038-persistence-jpa-api-surface.txt, 039-jpa-platform-capability-composition-test.txt |
2026-08-29 | fresh six-class API tests, public API-surface verification and app-bootstrap capability composition test all BUILD SUCCESSFUL | green existing tests do not contain the 2046–2048 cursor round-trip boundary property |
| EVD-024 | history | evidence/raw/040-persistence-jpa-api-history.txt |
2026-08-29 | cursor pre-decode bounds including decodedLengthOf were introduced in commit 2f5d2fc; capability/entity-not-found types date to initial JPA platform commit |
commit diffs show repository evolution but do not establish unstated author intent |
| SRC-045 | JPA transaction/failure code | src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/{transaction,failure}/**, matching dedicated tests |
same revision | complete 32-production/19-test transaction execution, retry, deadline, completion-evidence and operational-error implementation surface | real database lost-ack semantics and owning vendor translation require cross-scope evidence |
| SRC-046 | JPA transaction composition/docs | src/app-bootstrap/.../jpa/{JpaPlatformRuntimeAutoConfiguration,JpaTransactionAutoConfiguration}.java, PersistenceJpaRootAutoConfiguration.java, docs/jpa/{transaction-guide,support-matrix,runbooks}.md |
same revision | canonical PolicyTransactionPort implementation differs from public JPA executor/coordinator stack; Stable completion-evidence docs can be compared to actual bean construction |
static composition does not itself reproduce a network-level unknown commit |
| EVD-025 | JPA transaction static/runtime verification | evidence/raw/041-* through 051-* |
2026-08-29 | 51-file denominator/reachability/history, custom-policy probe, commit-ambiguity probe, fresh focused transaction tests and app-bootstrap wiring tests | fake transaction managers isolate control flow; they do not prove a real PostgreSQL commit was applied before acknowledgement loss |
| SRC-047 | Hibernate/Spring Data/Querydsl code/tests | src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/{hibernate,springdata,querydsl}/**, matching dedicated tests |
same revision | complete 42-production/11-test query/batch/stream/fetch/keyset/sort/Querydsl bounded sub-scope | PostgreSQL vendor internals and entire integration source set remain later owning scopes |
| SRC-048 | JPA query architecture/composition | JpaModuleBoundaryTest.java, app-bootstrap CleanArchitectureTest.java, persistence build.gradle/gradle.lockfile, NamedStatementInspector.java |
same revision | package DAG/export rules, Querydsl compile-only/runtime optionality, split export allowlists and missing statement-inspector production wiring | static reachability does not exclude reflection/external adopters and architecture rules do not prove runtime feature invocation |
| SRC-049 | JPA collection-fetch release evidence | src/config/jpa/release-registry.json, persistence build.gradle, HibernateCollectionFetchPaginationContractTest.java, PostgreSqlQueryPlanContractTest.java, root verifyJpaReleaseGateTasks |
same revision | blocking collection-fetch gate maps to a query-plan task selecting a different tag/test class, while target test itself does not inspect generated SQL limit | aggregate release task also runs the jpa-contract lane, so this proves per-gate provenance/assertion weakness rather than absence of all collection tests |
| EVD-026 | focused/architecture verification | evidence/raw/052-persistence-jpa-hibernate-springdata-querydsl-tests.txt, 055-persistence-jpa-query-architecture-tests.txt |
2026-08-29 | fresh 53-file-scope focused tests and package/bootstrap architecture tests BUILD SUCCESSFUL | existing tests omit the newly probed IDENTITY/Specification boundaries and cannot detect split-SSOT semantics |
| EVD-027 | runtime/library probes | evidence/raw/053-jpa-query-hibernate-boundary-probe.txt, 061-spring-data-specification-unrestricted-contract.txt |
2026-08-29 | property-access IDENTITY bypass, one-batch semantic edge, non-null null-predicate Specification acceptance, and Spring Data 4.0.7 unrestricted contract | controlled probes do not show a current production entity/repository actually uses the failing mappings |
| EVD-028 | PostgreSQL/release-gate verification | evidence/raw/057-persistence-jpa-query-hibernate-postgresql-contracts.txt, 058-persistence-jpa-queryplan-gate-task.txt, 059-verify-jpa-release-gate-tasks.txt |
2026-08-29 | selected real-PostgreSQL batch/ID/collection contracts pass; exact registry task executes only PostgreSqlQueryPlanContractTest; task-existence validator still passes |
green collection-fetch tests prove current assertions only, not SQL-side pagination |
| EVD-029 | reachability/history/provenance | evidence/raw/054-persistence-jpa-query-hibernate-reachability.txt, 056-persistence-jpa-collection-fetch-gate-provenance.txt, 060-persistence-jpa-query-hibernate-history.txt |
2026-08-29 | implementation adoption/wiring, release tag mismatch, and historical fixes/initial evidence design are recoverable from raw source/history | git history establishes evolution, not unstated intent |
| SRC-050 | PostgreSQL vendor code/tests/migrations | src/adapter/outbound/persistence-jpa/src/{main/java,main/resources,test/java}/**/postgresql/** | same revision | 55 production Java + 9 dedicated unit Java + 9 vendor migrations의 complete owning surface와 SQLSTATE/idempotency/inbox/outbox/native/COPY/type helper 구현 | complete PostgreSQL integration/readiness source set은 sub-scope 11 소유 |
| SRC-051 | PostgreSQL runtime composition | PostgreSqlPersistenceConfig, JpaPlatformRuntimeAutoConfiguration, JpaTransactionAutoConfiguration, PostgreSqlIdempotencyProviderConfig, DefaultJpaRetryPolicy | same revision | vendor translator가 transaction failure chain에, PostgreSQL Idempotency V2 store가 provider composition에 실제 연결됨 | 모든 profile/deployment가 동일 bean set을 사용한다는 보장은 아님 |
| SRC-052 | reliability contracts/history | application-core/.../{idempotency,inbox,outbox}/**, docs/superpowers/specs/2026-07-28-jpa-production-capability-design.md, docs/reviews/2026-08-14-jpa-module-code-review.md | same revision/current history | replay TTL, owner-safe transition, completion-unknown/reconciliation 기대 계약과 과거 wiring findings를 현재 구현과 비교 | 문서만으로 runtime behavior를 증명하지 않으므로 probes와 교차검증 |
| EVD-030 | real PostgreSQL probe | evidence/raw/062-postgresql-replay-semantic-probe.txt, 062a-postgresql-replay-semantic-probe.java | 2026-08-29 | same-store inbox forged-owner replay와 changed-retention, polling outbox changed-schedule replay를 PostgreSQL 16.15에서 재현 | 해당 inbox/outbox adapters는 현재 default production composition에서 확인되지 않은 candidate |
| EVD-031 | translator/policy probes | evidence/raw/063-postgresql-40003-probe.txt, 069-postgresql-40003-policy-probe.txt | 2026-08-29 | SQLSTATE 40003이 UNKNOWN/completionUnknown=false가 되고 실제 DefaultJpaRetryPolicy에서 RECONCILE가 아니라 FAIL로 결정됨 | synthetic SQLException 40003; 실제 network commit acknowledgement loss 자체를 재현한 것은 아님 |
| EVD-032 | codec probe | evidence/raw/065-pg-range-escaped-quote-probe.txt, 065a-pg-range-escaped-quote-probe.java | 2026-08-29 | current PgRangeCodec의 escaped quote/backslash endpoint self-round-trip 실패 | pure codec probe; real PostgreSQL text output/provider consumer는 실행하지 않음 |
| EVD-033 | real PostgreSQL idempotency probe | evidence/raw/066-postgresql-idempotency-replay-boundary-probe.txt, 066a-postgresql-idempotency-replay-boundary-probe.java | 2026-08-29 | changed replayTtl false-same completion과 expired COMPLETED inspect/claim lifecycle divergence를 production store + PostgreSQL 16에서 재현 | temporary analysis tests; 실행 후 repository source에서 제거/복원 |
| EVD-034 | command | evidence/raw/067-persistence-jpa-postgresql-unit-tests.txt | 2026-08-29 | 9 dedicated PostgreSQL unit classes fresh --rerun-tasks BUILD SUCCESSFUL | existing assertions가 새 replay/expiry/range/40003 policy boundaries를 포함하지 않음 |
| EVD-035 | reachability/history | evidence/raw/064-postgresql-vendor-manifest-reachability.txt, 068-postgresql-vendor-history-review-provenance.txt | 2026-08-29 | 73-file denominator, key production construction, current history와 prior-review exact-term provenance | static reachability는 reflection/external adopter/runtime activation을 완전히 증명하지 않음 |
| SRC-053 | JPA baseline capability code/tests/migrations | evidence/raw/070-persistence-jpa-baseline-capability-manifest.txt, baseline audit/auditing/cache/envers/h2/idempotency/liveevent/lock/migration/observation/operation/outbox/security/config sources | same revision | 61 production + 19 dedicated test + 7 migration SQL, 87/87 FULL_READ | complete PostgreSQL integration lane belongs to sub-scope 11 |
| SRC-054 | baseline composition/security provenance | evidence/raw/072-baseline-capability-reachability.txt, JpaAdapterComponentsConfig, JpaPlatformRuntimeAutoConfiguration, JpaPlatformReport, docs/jpa/security.md | same revision | outbox is baseline-composed, liveevent/durable adapters are not; runtime-role Stable contract promises startup fail-fast but production never invokes requireSafe, and report only checks CREATE privilege | static caller search does not cover external applications constructing these public types themselves |
| EVD-036 | real PostgreSQL probe | evidence/raw/071-liveevent-full-sweep-probe-output.txt, 071a-liveevent-full-sweep-probe.java | 2026-08-29 | after a stream is fully swept, current-row max(position) becomes null and allocator reuses position 1 on PostgreSQL 16 | temporary analysis test; adapter is currently not default-composed |
| EVD-037 | real PostgreSQL probe | evidence/raw/073-durable-operation-expired-lease-output.txt, 073a-durable-operation-expired-lease-probe.java | 2026-08-29 | expired lease owner can still update RUNNING operation to SUCCEEDED before takeover because terminal update lacks lease-expiry predicate | temporary analysis test; adapter is currently not default-composed |
| EVD-038 | focused adapter probe | evidence/raw/075-outbox-stale-worker-state-regression-output.txt, 075a-outbox-stale-worker-state-regression-probe.java | 2026-08-29 | baseline outbox markFailed can regress a PUBLISHED entity to FAILED with no owner/attempt/state CAS fencing | focused unit-level transition probe; multi-worker database timing itself is inferred from separately committed claim/relay transaction structure |
| EVD-039 | command | evidence/raw/076-persistence-jpa-baseline-unit-tests.txt | 2026-08-29 | fresh full :adapter:outbound:persistence-jpa:test --rerun-tasks BUILD SUCCESSFUL, 18 actionable tasks executed | unit lane does not replace real-PostgreSQL semantics, which are separately probed where required |
| SRC-055 | Fileserver persistence + migrations | evidence/raw/077-persistence-jpa-fileserver-manifest.txt, src/adapter/outbound/persistence-jpa/src/main/{java,resources}/**/fileserver/** | same revision | 25 production Java + 4 migration SQL, 29/29 FULL_READ; capability is opt-in but production-composed when enabled | PostgreSQL integration/readiness source denominator remains sub-scope 11 |
| SRC-056 | Fileserver quota/composition/schema contracts | evidence/raw/079-fileserver-reachability-quota-schema-contract.txt, application Fileserver quota/admission code, Fileserver schema activation, design deviations/plan | same revision | production quota aggregate readers/byte ceiling are absent; V3/V4 schema changes are not represented in registry revision while activation accepts >=2 | static cross-scope search cannot prove behavior of external adopters outside this repository |
| EVD-040 | real PostgreSQL probe | evidence/raw/078-fileserver-quota-boundary-probe-output.txt, 078a-fileserver-quota-boundary-probe.java | 2026-08-29 | expired direct reservation still commits; reclaim request spanning 65 one-byte committed rows leaves 1 byte because only 64 rows are loaded | temporary analysis tests added to Fileserver reclamation class and restored after run |
| EVD-041 | real PostgreSQL concurrency probe | evidence/raw/080-fileserver-recovery-concurrent-enqueue-output.txt, 080a-fileserver-recovery-concurrent-enqueue-probe.java | 2026-08-29 | two simultaneous first enqueue calls for one file produce one success + one DataIntegrityViolationException, with one row retained | scheduling is barrier-assisted but exact winner is nondeterministic as expected |
| EVD-042 | real PostgreSQL migration probe | evidence/raw/081-fileserver-schema-activation-v2-output.txt, 081a-fileserver-schema-activation-v2-probe.java | 2026-08-29 | Fileserver Flyway target 2 promoted ACTIVE passes FileserverSchemaActivation while V3 claim_token and V4 lifecycle_state columns are absent | demonstrates gate false-positive; full Spring context with ddl-auto=none was not separately booted |
| EVD-043 | command | evidence/raw/082-fileserver-official-readiness-lanes.txt | 2026-08-29 | original-source Fileserver migration/metadata/reclamation PostgreSQL readiness tasks fresh --rerun-tasks BUILD SUCCESSFUL, 21 actionable tasks executed, git clean before/after | these official assertions do not include the temporary boundary probes, which are captured separately |
| EVD-044 | real PostgreSQL liveness probe | evidence/raw/079-fileserver-cleanup-crash-budget-output.txt, 079a-fileserver-cleanup-crash-budget-probe.java | 2026-08-29 | Fileserver cleanup의 declared max attempt 8을 넘겨 crash-reclaim만으로 attempt 9가 되고도 row가 FAILED / CLAIM_LEASE_EXPIRED로 다시 claim 가능함을 재현 | controlled repeated lease-expiry simulation; physical storage crash 자체를 발생시킨 것은 아니며 probe 종료 후 analysis-owned test source는 exact HEAD blob으로 복구됨 |
| SRC-057 | Notification persistence + migrations | evidence/raw/083-persistence-jpa-notification-manifest.txt, src/adapter/outbound/persistence-jpa/src/main/{java,resources}/**/notification/** + 5 dedicated unit tests | same revision | 53 production Java + 10 migrations + 5 unit Java, 68/68 FULL_READ; request/recipient/attempt/admin/reconciliation/provider-event/inbox persistence and opt-in composition | full PostgreSQL integration/readiness denominator remains sub-scope 11 |
| SRC-058 | Notification runtime reachability/contracts | evidence/raw/092-notification-reachability-test-gap.txt, NotificationDispatchService, DispatchOutcomeRecorder, ReconciliationJobWorker, NotificationAdminApplicationService | same revision | post-provider recorder uses lease-unaware save, reconciliation processing is outside durable claim, admin atomic claim has no production caller, V4 is final registry revision write | static call graph is repository-internal and does not cover external adopters |
| EVD-045 | real PostgreSQL schema probe | evidence/raw/084-notification-schema-v4-activation-probe.txt | 2026-08-29 | V4-only ACTIVE database passes activation count while current-required expires/projection/collapse/admin/evidence columns are absent | full Spring context boot was not required to demonstrate gate predicate false-positive |
| EVD-046 | real PostgreSQL lease probes | evidence/raw/085-notification-expired-lease-write-probe.txt, 091-notification-stale-provider-overwrite-probe.txt | 2026-08-29 | expired holder is not still-held yet owner+fence update succeeds; after worker B takeover an ID-only stale projection overwrites lifecycle while preserving B/fence 8 | SQL reproduces exact predicates/effect; provider network call itself is not simulated |
| EVD-047 | real PostgreSQL reconciliation probe | evidence/raw/086-notification-reconciliation-claim-probe.txt | 2026-08-29 | two sequential autocommit FOR UPDATE SKIP LOCKED claims return the same due job before any complete/reschedule, proving select-lock lifetime does not cover worker processing | controlled two-session semantics; provider status query itself is not executed |
| EVD-048 | admin claim/reachability probe | evidence/raw/087-notification-admin-claim-completion-probe.txt, 088-notification-admin-claim-reachability.txt | 2026-08-29 | atomic claim row cannot be completed by current save-style duplicate insert, and production operations.claim() call sites are zero while find→action→save remains | direct SQL + static repository call graph |
| EVD-049 | fresh official Notification verification | evidence/raw/089-notification-schema-official-readiness.txt, 090-notification-existing-contracts-fresh.txt | 2026-08-29 | schema readiness and existing recipient/admin claim contracts both BUILD SUCCESSFUL with --rerun-tasks, 19/19 tasks each | green tests validate existing assertions; they omit current-schema compatibility, post-provider lease write, reconciliation claim lifetime, and production admin claim wiring |
| SRC-059 | Experimental platform code/tests/migration | evidence/raw/093-persistence-jpa-experimental-manifest.txt, src/adapter/outbound/persistence-jpa/src/main/java/**/experimental/**, dedicated unit tests, db/experimental-rls/V1__tenant_rls.sql | same revision | 29 production + 8 unit + 1 SQL의 38/38 owning FULL_READ와 multi-tenancy/RLS/schema/database tenancy/read-replica/next-compatibility surface | 현재 app-bootstrap production wiring은 확인되지 않아 semantic defects는 latent로 분류 |
| SRC-060 | Experimental composition/consent | evidence/raw/096-experimental-gate-reachability.txt, 099-experimental-structural-optin-gap.txt, ExperimentalEntryConsentTest, PersistenceJpaConfig, JpaModuleBoundaryTest | same revision | 일부 activation-capable public constructor가 gate list 밖에 있고 Stable entity/repository scan 문자열이 experimental package를 포함하지만 현재 experimental JPA stereotype은 0 | external consumers/reflection까지 증명하지 않으며 현재 repository production caller는 0 |
| EVD-050 | focused semantic probes | evidence/raw/095-experimental-pool-overshoot-probe.txt, 097-experimental-replica-provider-probe.txt | 2026-08-29 | heterogeneous pool 8+5가 max 10을 넘어 13으로 열림; no-evidence EVENTUAL read가 REPLICA; unknown Hibernate 9가 Stable replacement 허용됨 | analysis-only temporary unit tests; source는 실행 후 복원 |
| EVD-051 | real PostgreSQL security probe | evidence/raw/098-experimental-rls-missing-table-probe.txt | 2026-08-29 | PostgreSQL 16에서 RLS verifier가 requested missing tenant table을 exception 없이 성공으로 인정 | current app runtime does not compose RLS verifier; demonstrates verifier contract only |
| EVD-052 | fresh original Experimental verification | evidence/raw/100-experimental-original-unit-tests.txt, 101-experimental-original-postgresql-contracts.txt | 2026-08-29 | original 8 experimental unit + boundary/scan tests and 5 PostgreSQL contract/migration/security classes all BUILD SUCCESSFUL; git clean before/after | existing green assertions omit the newly probed missing-table, partial pool headroom, no-evidence EVENTUAL, unknown-major and exhaustive opt-in boundaries |
| SRC-061 | JPA testkit + fixture/unit corpus | evidence/raw/102-persistence-jpa-testkit-manifest.txt, src/adapter/outbound/persistence-jpa/src/testkit/java/**, src/adapter/outbound/persistence-jpa/src/test/java/**/testkit/** | same revision | 41 testkit + 21 fixture/unit Java, 62/62 FULL_READ; architecture/query-plan/release/migration/failure/pool helper semantics | production persistence behavior 자체가 아니라 evidence producer의 정확성을 분석 |
| EVD-053 | testkit semantic false-negative probes | evidence/raw/103-testkit-unit-boundary-probes.txt | 2026-08-29 | CompletableFuture<Entity> architecture leak accepted; audit decoy parameter accepted; nested child estimate 1000x miss가 ratio 1.0으로 축약; UUID test fixture same-ms inversion 3784에서 재현 | UUID helper는 exact FQN consumer 0이라 production defect로 승격하지 않음 |
| EVD-054 | real PostgreSQL EXPLAIN side-effect probe | evidence/raw/104-testkit-explain-dml-cte-probe.txt | 2026-08-29 | SELECT-only guard가 data-modifying CTE를 허용해 EXPLAIN ANALYZE 후 row bucket 9 -> 99; PostgreSQL 16 BUILD SUCCESSFUL | current committed query-plan inputs는 SELECT이므로 current release mutation을 주장하지 않음 |
| EVD-055 | testkit reachability sweep | evidence/raw/105-testkit-public-reachability-sweep.txt | 2026-08-29 | production/release-connected helpers와 zero-reference CommitAmbiguityProxy, PostgreSqlContractExtension 구분 | simple-name collision은 exact FQN 추가 확인으로 보정 |
| EVD-056 | fresh original testkit evidence | evidence/raw/106-testkit-original-verification.txt | 2026-08-29 | JPA full unit 29s green, production JPA architecture 1m47s green, original PostgreSQL query-plan 25s green; git clean before/after | green suite가 newly probed wrapper/CTE/child-plan/substring boundaries를 포함하지 않음 |
| SRC-062 | governance / build / config | evidence/raw/107-persistence-jpa-governance-manifest.txt, adapter/outbound/persistence-jpa/{CLAUDE.md,README.md,build.gradle,gradle.lockfile}, config/**, JpaModuleBoundaryTest, CandidateAdapterCompositionTest | same revision | leaf 최상위 4 + production 4 + test 3 = 11/11 FULL_READ; strictTestLanes/testkitPublisher/apiSurface 계약, 24-package catalog와 export list, always-install 대 opt-in scan 경계 | sub-scope 06이 이미 계상한 config/platform test 3개는 여기서 재계상하지 않으며, 그 test의 내용 분석만 이 sub-scope가 수행 |
| SRC-063 | composition reachability | evidence/raw/108-governance-config-reachability.txt, PersistenceJpaRootAutoConfiguration, CaSkeletonApplication, PostgreSqlPersistenceConfig, H2PersistenceConfig, PersistenceVendorProdSafetyValidator | same revision | config public type 3개의 leaf 밖 소비자 존재; leaf @ConfigurationProperties 3형제 중 PersistenceVendorSettings만 production enablement 부재; composition root @ConfigurationPropertiesScan이 persistence tree를 덮지 않음 | 정적 검색은 reflection/외부 adopter를 덮지 않는다; prod safety validator는 h2 값만 거부하므로 unknown 값 검증과 무관 |
| EVD-057 | 실행 probe | evidence/raw/109-vendor-selector-shipped-shape-probe.txt, 109a-vendor-selector-shipped-shape-probe.java | 2026-08-29 | shipped 모양 + vendor=mysql에서 context 성공·settings bean 0·SPI bean 0·양 vendor config 0; @EnableConfigurationProperties 추가 시 property를 지목하는 ConfigurationPropertiesBindException; component scan 포함 case의 실패 메시지에 vendor property 부재 | ApplicationContextRunner context이지 full application context가 아니므로 실제 배포에서 최초로 실패하는 bean은 다를 수 있음; 임시 test는 실행 후 삭제하고 git clean 확인 |
| SRC-064 | documentation / count drift | evidence/raw/110-governance-doc-count-drift.txt, src/build.gradle:verifyDocumentedLeafCount, docs/jpa/repository-adaptation.md, docs/architecture/jpa-api-surface.txt, JpaModuleBoundaryTest, CleanArchitectureTest, leaf README.md | same revision | registry 44 대 문서/주석의 19-leaf 6곳; public top-level type 338/350 대 주석의 318/324; README의 package root·module 이름 drift; gate 탐색 domain이 CLAUDE.md/build.gradle 두 파일명뿐 | drift는 문서·주석에 한정되며 런타임 동작에 영향 없음; gate 자체는 green으로 통과함을 별도 실행으로 확인 |
| SRC-065 | pool lane | evidence/raw/111-persistence-jpa-pool-lane-manifest.txt, 112-pool-lane-claim-registry-reachability.txt, src/jpaPlatformPerformanceTest/**, config/jpa/release-registry.json, docs/jpa/support-matrix.md, .github/workflows/jpa-nightly.yml | same revision | 3/3 FULL_READ; release registry gate 6개에 pool lane 부재(3곳 모두 exit=1)이나 jpaPlatformReleaseGate는 의존; lane assertion 8개 중 2개가 공식 항등식이고 pending 관측 assertion 부재 | verifyJpaReleaseGateTasks는 registry→task 한 방향만 검사하므로 역방향 미검증 사실은 정적 관찰 |
| EVD-058 | 실제 PostgreSQL probe | evidence/raw/113-pool-lane-saturation-probe.txt, 113a-pool-lane-saturation-probe.java | 2026-08-29 | 실제 포화 Hikari pool에서 active=2/idle=0/pending=1/saturated=true, 반납 후 대기자 획득; acquisition 실측 504ms 대 설정 500ms 대 assertion 상한 2,500ms | 단일 머신 관측이며 성능 수치가 아니라 계약 관측; 임시 test는 실행 후 삭제하고 git clean 확인 |
| EVD-059 | fresh original verification | evidence/raw/114-governance-pool-original-verification.txt | 2026-08-29 | 원본 소스에서 leaf unit lane 28s green(18 executed), jpaPlatformPoolContractTest 24s green(18 executed), root verifyDocumentedLeafCount 3s green(9 executed), git clean before/after | green은 기존 assertion의 통과를 뜻하며 §119·§125가 지적한 미검증 영역을 포함하지 않는다 |
| SRC-066 | integration/readiness lane corpus | evidence/raw/120-persistence-jpa-integration-lane-manifest.txt, src/postgresqlIntegrationTest/** | same revision | 75/75 FULL_READ(71 Java + 4 SQL, 13,977 lines); tag 5종 분포, 무-tag 클래스 13개와 readiness task 14개의 1:1 대응, orphan test 0 | 파일 소유는 이 sub-scope이나 §52(collection-fetch)·sub-scope 10(explain runner) 등 이미 판정된 결함은 중복 계상하지 않음 |
| SRC-067 | evidence 배선(card ↔ lane ↔ gate) | config/jpa/readiness-cards.yaml, src/gradle/jpa-evidence.gradle, config/jpa/release-registry.json, .github/workflows/{ci-quality-gates,jpa-nightly,jpa-pr,jpa-release,jpa-r2-evidence}.yml | same revision | card 17개 중 active 13, producer 12; card scenario가 가리키는 클래스 12개는 전부 readiness/**이고 platform/** 33개는 0개; readiness task는 jpaPlatformReleaseGate에 없고 workflow가 직접 부르지도 않음 | 배선은 --dry-run task graph resolve로 확인했으며, CI 실제 실행 이력은 이 저장소 안에서 확인할 수 없다 |
| EVD-060 | command | evidence/raw/115-integration-lane-original-verification.txt | 2026-08-29 | 원본 소스에서 5개 tag lane --rerun-tasks BUILD SUCCESSFUL in 3m 10s — 51 classes / 244 tests / 0 skipped / 0 failures / PostgreSQL 컨테이너 87회 기동, git clean before/after | 같은 실행에 이어 붙인 verifyJpaCandidateEvidence는 :app-bootstrap:test의 compose scenario가 jq 부재로 실패해 완주하지 못했다(환경 제약, app-bootstrap 소유) |
| EVD-061 | command | evidence/raw/116-readiness-lane-original-verification.txt, 118-readiness-task-result-matrix.txt | 2026-08-29 | 14개 readiness task --rerun-tasks --continue 결과 표: 82 tests / 0 skipped / 12 PASS / 2 FAIL, git clean before/after | postgresqlSecurityBaselineIntegrationTest의 실패는 인증서 SAN이 localhost 단일이라 형제 컨테이너 환경에서 매핑 포트에 닿지 못한 환경 제약이며 repository 결함이 아니다 |
| EVD-062 | 실패 재현 + history | evidence/raw/117-flyway-migration-readiness-lane-failure.txt | 2026-08-29 | postgresqlMigrationIntegrationTest 단독 --rerun-tasks BUILD FAILED/exit 1, 두 assertion 실패 원문(1,3,4,5,6,9,10,11,12 대 1,3,4,5,6; 1,2 대 1), stream 파일 목록, assertion 최종 수정 2026-07-31 대 migration 추가 08-15/08-18/08-28 | 원본 unmodified source, git clean before/after; CI가 현재 red인지 여부는 저장소 안에서 확인할 수 없고 확인된 것은 이 revision에서 task가 실패한다는 사실이다 |
| EVD-063 | 실제 PostgreSQL probe | evidence/raw/119-notification-migration-ladder-probe.txt, 119a-notification-migration-ladder-probe.java | 2026-08-29 | notification 사다리 4종의 컬럼 집합 실측: V1–V10 218, V1–V9 218(차 0), V1–V8 213(차 5), V1–V6 208(차 10)과 누락 컬럼 이름 전체 | 컬럼 집합 비교이며 데이터·제약 semantics 비교가 아니다; V10이 DDL 없는 guard이기 때문에 V9와 V10의 컬럼 수가 같다 |
| SRC-068 | cross-scope 정합 | HibernateCollectionFetchPaginationContractTest, PostgreSqlQueryPlanContractTest, PostgreSqlSecurityContractTest, TenantPoolCapacityContractTest, AdminOperationClaimContractTest | same revision | 앞선 sub-scope 04·06·08·09·10의 결함이 이 lane에서 green으로 남은 이유를 각 test의 assertion 범위로 설명(SQL limit 미확인, CTE 미포함, test가 만든 role/policy, 균일 pool 크기, test가 재작성한 claim SQL) | 정합 설명이며 새 결함 판정이 아니다 |
| SRC-069 | module map / denominator | evidence/raw/121-persistence-mongo-module-inventory.txt, src/adapter/outbound/persistence-mongo/** | same revision | mongo leaf 497 tracked files(main 353 / test 104 / testkit 35 / perf 1 / top-level 4), 약 38.5k LOC, production Java 351, package 지도, 선언된 8개 test lane | 초기 sizing이며 각 sub-scope의 최종 denominator는 그 sub-scope manifest가 확정한다 |
| SRC-070 | governance / opt-in scope | evidence/raw/122-mongo-governance-optin-manifest.txt, mongo CLAUDE.md/README.md/build.gradle/gradle.lockfile, root package 4, autoconfigure/** 9, META-INF 등록 resource 2, 관련 test 12 | same revision | 31/31 FULL_READ; opt-in 네 겹(import filter → root auto-config → persistence config → platform/observability auto-config)과 각 겹이 막는 실패, startup validator/probe requirement 배치 | 이 sub-scope의 도달성은 Java import graph가 아니라 등록 metadata와 annotation 인자에 있어 정적 참조 검색만으로 판단할 수 없다 |
| SRC-071 | opt-in reachability / sibling / duplicate | evidence/raw/123-mongo-optin-reachability-and-siblings.txt, CapabilityDependencyValidator, CapabilityDependencyStartupCheck, application.yml:370 | same revision | root/autoconfigure public type 13개 중 leaf 밖 참조는 2개; master switch를 읽는 production 지점 6곳이 조건 동일; ca-skeleton.persistence-mongo.* namespace의 네 번째 key active-profile만 소유자가 leaf 밖 | 정적 검색은 reflection·생성 등록·저장소 밖 adopter를 덮지 않는다 |
| EVD-064 | 실행 probe | evidence/raw/124-mongo-platform-settings-binding-probe.txt, 124a-mongo-platform-settings-binding-probe.java | 2026-08-29 | change-streams=true → 예외 없이 bound value false; transactions=true → true 보존; required-secondaries=-1 → MongoOperationRejectedException으로 context 실패 | binding 계층만 관측했고 change stream 실행체 자체는 이 저장소에 shipped되지 않는다; 임시 test는 실행 후 삭제하고 git clean 확인 |
| SRC-072 | documentation / count drift | evidence/raw/125-mongo-governance-doc-count-drift.txt, mongo build.gradle, docs/architecture/mongo-api-surface.txt, MongoNamespaceContractTest, MongoModuleBoundaryTest, docs/mongodb/repository-adaptation.md, docs/adr/ADR-MONGO-001 | same revision | build.gradle 주석의 311/313 대 실측 346/351, 382 대 실측 526; namespace guard의 domain(src/main/**)과 그 밖에 생존한 폐기 키 3+2곳; 19-leaf claim 3곳 대 registry 44; README "10개 규칙"은 방향 규칙 개수로 정확 | drift는 주석·문서에 한정되며 런타임 동작에 영향 없음; 관련 gate는 모두 green임을 별도 실행으로 확인 |
| EVD-065 | fresh original verification | evidence/raw/126-mongo-hermetic-lane-original-verification.txt | 2026-08-29 | 원본 소스 --rerun-tasks: unit lane 14 classes/72 tests, stable contract lane 83 classes/526 tests, 둘 다 0 skipped/0 failures; verifyMongoTestLaneDisjointness·verifyMongoReleaseContractLanes·verifyMongoApiSurface 통과; :app-bootstrap:test --tests *CapabilityDependencyValidatorTest* 통과; git clean before/after | hermetic lane만 실행했고 Docker 기반 6개 lane(replicaSet/failover/migration/compatibility/security/performance)은 이 실행에 포함되지 않는다 |
| SRC-073 | api core contract | evidence/raw/127-mongo-api-scope-manifest.txt, adapter/outbound/persistence-mongo/src/main/java/**/api/** + 전용 test 9 | same revision | 70/70 FULL_READ(61 production 2,687 LOC + 9 test); operation identity·실행 context·실패 algebra·BSON 표현 manifest·consistency registry·schema version 정책·관측 seam; committed public surface 346 중 api 기여 59 | api는 의도된 외부 표면이라 저장소 내부 참조 0이 dead를 뜻하지 않으며, 저장소 밖 adopter는 정적 검색으로 증명되지 않는다 |
| SRC-074 | api negative-space probes | evidence/raw/128-mongo-api-negative-space-probes.txt, MongoFailureContext, MongoTransaction*Exception, MongoSchemaVersionPolicy, DefaultMongoFailureTranslator, MongoConsistencyDescriptor, Database/CollectionProfileName | same revision | framework-free 규칙 소스 전수 검색 매치 0; schema-version 예외 두 생성 경로의 category/버전 비대칭; MongoTimeoutException 2-arg 생성자의 initCause와 그 규칙을 검사하는 test의 대상 불일치; invariant를 강제하는 타입과 강제하지 않는 타입 6종 비교; 두 profile-name record의 검증 코드 동일성 | 정적 판정이며 실행 probe를 필요로 하지 않았다; production 경로의 정합성(classification 파생)은 코드 경로 추적으로 확인했고 런타임 실행으로 재확인하지는 않았다 |
| EVD-066 | 실행 probe | evidence/raw/129-mongo-empty-type-registry-write-probe.txt, 129a-...java | 2026-08-29 | 빈 type registry로 MappingMongoConverter.write(...) → IllegalStateException: no type metadata policy is registered for …; Spring 기본 mapper는 같은 입력에서 _class 포함 3키를 씀; policyFor→CLASS_METADATA_ALLOWED, writeTypeRestrictions는 _class를 쓰고 writeType은 던진다 | 단일 converter 경로만 관측했고 repository·template 상위 경로 전체를 실행하지 않았다; 임시 test는 실행 후 삭제하고 git clean 확인 |
| SRC-075 | mapping / nativecap / geo | evidence/raw/130-mongo-mapping-nativecap-geo-manifest-and-probes.txt | same revision | 27/27 FULL_READ; BSON 표현 manifest의 converter 등록 경로, native capability gateway의 노출 규칙, geospatial operations의 sphere-index 요구; reachability·조건부 형제·중복 mechanism probe | 정적 판정 중심이며 geo 경로는 실제 2dsphere index를 가진 서버에서 재확인하지 않았다 |
| SRC-076 | imperative / reactive 실행 경로 | evidence/raw/131-mongo-execution-paths-manifest-and-probes.txt | same revision | 61/61 FULL_READ; 두 executor의 관측·실패번역·deadline 처리와 collection profile registry 경유 규칙; deadline 미부착 지점과 실행 scope 이탈 경로 식별 | 두 executor의 배선은 auto-configuration 정적 판독으로 확인했고 런타임 컨텍스트로 재확인하지 않았다 |
| SRC-077 | query / aggregation | evidence/raw/132-mongo-query-aggregation-manifest-and-probes.txt | same revision | 29/29 FULL_READ; allowlist 기반 query 표현 불가능성, keyset cursor HMAC·타입태그·길이 프레이밍; 배선된 bean은 MongoBudgetEnforcer 하나이고 그 소비자도 미배선; aggregation executor가 collection을 String으로 받아 registry·실행 scope를 우회 | 두 finding 모두 정적으로 결정 가능해 실행 probe를 돌리지 않았다; 미배선이므로 현재 노출은 없다 |
| SRC-078 | transaction / retry / session | evidence/raw/133-mongo-transaction-manifest-and-probes.txt | same revision | 27/27 FULL_READ; body 재시도와 commit 재시도의 두 루프 분리를 blocking·reactive 양쪽에서 코드로 추적; transaction subsystem bean 0·cross-package 참조 0인데 platform.transactions=true는 startup에서 TRANSACTION capability를 요구 | 미배선 판정은 이 leaf 안의 정적 검색 결과이며 저장소 밖 adopter는 덮지 않는다 |
| SRC-079 | schema / migration | evidence/raw/134-mongo-schema-migration-manifest-and-probes.txt | same revision | 58/58 FULL_READ; manifest 기반 선언과 D4 apply 사다리, migration lease의 fencing token 설계; apply policy·diff engine·TTL validator의 production 소비자 0; mongoMigrationTest lane 1 class/8 tests/0 failures | apply policy 계층의 미배선은 이 leaf 범위의 검색 결과다; ledger의 ensureIndexes 전제는 운영 배포 시점에만 확인 가능하다 |
| EVD-067 | 실행 probe | evidence/raw/134a-mongo-schema-migration-execution-probes.txt | 2026-08-30 | 실서버(MongoDB 8.0 replica set): saveCheckpoint(fence=1 over stored 5) REFUSED / recordApplied(fence=1 over stored 5) ACCEPTED → 밀려난 runner가 ledger를 차지하고 live runner는 driver duplicate-key를 받음; hermetic: TTL·sparse·partial·collation 변경과 서버-숨김 index가 전부 diff.isClean()=true; MongoIndexManifest.expireAfter(1s) 생성 성공; Flamingock lease로 non-resumable migration도 REFUSED | ledger 경로만 직접 호출했고 MongoMigrationRunner.applyOne의 인접 lock.refresh 보호는 별도로 코드로 확인했다; 임시 test 2개는 실행 후 삭제하고 git clean 확인 |
| SRC-080 | changestream | evidence/raw/135-mongo-changestream-manifest-and-probes.txt | same revision | 26/26 FULL_READ; source bean은 무조건·consumer bean은 fork의 5종 SPI에 조건부로 실제 조립됨; changeStreams flag는 false 고정이라 startup CHANGE_STREAM 검사 도달 불가; recovery의 네 결정 메서드 중 하나만 사용되고 MongoChangeHistoryLostException은 어디에서도 생성되지 않음; 세 기존 test가 "본 적 있지만 완료되지 않은 위치"를 다루지 않는 이유 | SPI 구현은 전부 test fixture이며 실제 fork 배선을 관측한 것은 아니다 |
| EVD-068 | 실행 probe | evidence/raw/135a-mongo-changestream-execution-probes.txt | 2026-08-30 | auto-configuration과 동일 조립으로 3종: (C) worker 1개·failover 중 투영 취소 → 재전달 이벤트가 pipeline에 삼켜지고 checkpoint가 그것을 지나침, state=RUNNING·runbook 빈칸·Flux 정상 완료; (A) BUSY+resumable 실패에서 동일 소실; (B) 실패 없이도 후속 이벤트가 CLAIMED_ELSEWHERE 위치를 지나침; (D) requireCorrectResumeOption은 자기 자신과 비교 | reactor 기반 hermetic 재현이며 실제 서버의 change stream 재전달 순서를 관측한 것은 아니다(재전달 대상은 stored checkpoint 기준으로 구성); 임시 test 2개는 실행 후 삭제하고 git clean 확인 |
| SRC-081 | security / failure / observation / client | evidence/raw/136-mongo-security-failure-observation-client-probes.txt | same revision | 44/44 FULL_READ; failure는 완전 배선(classifier·translator bean, 두 executor가 사용), security 검증 경로는 MongoStartupValidator가 실행, observation은 driver 리스너만 customizer로 설치, client는 저장소 전체 호출자 0; allowlist 강제·redactor describe·잔여 API 4종의 production 호출 0 | 저장소 밖 adopter가 MongoClientSettingsFactory를 쓰는 경우는 정적 검색으로 배제할 수 없다 |
| EVD-069 | 실행 probe | evidence/raw/136a-mongo-client-settings-execution-probe.txt | 2026-08-30 | MongoSecurityProfile.production(tls=true, auth=true)를 validator가 ACCEPTED; Boot가 README의 spring.data.mongodb.uri에서 만드는 설정은 sslEnabled=false, connect 10000ms, serverSelection 30000ms, poolMaxSize 100, serverApi=null, uuidRepresentation=UNSPECIFIED; factory가 만들었다면 sslEnabled=true | 실제 Spring 컨텍스트가 아니라 Boot가 사용하는 동일 API로 재구성한 비교다; 임시 test는 실행 후 삭제하고 git clean 확인 |
| SRC-082 | advanced 전체 | evidence/raw/137-mongo-advanced-manifest-and-probes.txt | same revision | 75/75 FULL_READ; guard bean은 auto-load되지 않는 MongoAdvancedConfiguration에만 있어 기본 배선에서 모든 entry point 도달 불가(설계와 일치); 구체 클래스 19개 = entry point 7 + policy 11 + 의도적 제외 1(@Configuration); 실행 probe: 모든 승인 증거를 갖춘 입력에서 sharding 4작업 중 1개만 실행(3개는 5인자 execute의 approval=null로 거부); promotion 증거 어휘 2종·checkpoint 작성자 2곳·Scaffold 고지 누락 1건 | 임시 probe test는 실행 후 삭제하고 git clean 확인; Advanced 능력의 실제 동작은 해당 토폴로지가 없어 검증 불가 |
| SRC-083 | testkit / release / lanes | evidence/raw/138-mongo-testkit-release-lanes-probes.txt | same revision | 49/49 FULL_READ; testkit 33종 소비자 계수에서 MongoRoundTripContract·MongoAtlasLocalContainer·MongoChunkMigrationController 0; MongoStableContractSuite의 (not executed) 분기와 certified() 커버리지 검사가 구조적으로 도달 불가(형제 MongoChaosGate는 정상); release-contracts.json의 차단 계약 3개가 전부 topology=none hermetic이고 experimental 3개는 등록되지 않은 task를 가리킴; .github/workflows 26개 중 mongo 언급 0(JPA는 7개) | CI 부재는 이 저장소의 workflow 파일 기준이며 외부 파이프라인은 관측 범위 밖이다 |
| SRC-084 | module map / denominator | evidence/raw/139-identifier-module-inventory.txt, src/adapter/outbound/identifier/** | same revision | leaf 전체 10 tracked files(main Java 4 / test Java 1 / test Groovy 1 / governance 4), 562 LOC; 단일 패키지 dev.caskeleton.adapter.outbound.identifier; 레지스트리 allowed_dependencies=[domain-core, application-core], runtime_memberships=[app-bootstrap, sample-portfolio]; 소비자는 app-bootstrap·sample-portfolio 2곳 | 10 파일 전수이므로 sampling 없음; 저장소 밖 adopter는 덮지 않는다 |
| SRC-085 | reachability / doc drift | evidence/raw/140-identifier-negative-space-probes.txt | same revision | 세 production 타입 소비자 계수(UuidCodec 0, 나머지 둘은 composition root 배선); UuidCodec. 호출은 자기 Spock 스펙 5줄뿐이고 leaf 밖 20+ 파일이 UUID.fromString을 직접 호출, D10 대상은 Hibernate @JdbcTypeCode(SqlTypes.UUID)가 처리; CLAUDE.md의 build.gradle 선언 서술 3항목 불일치; README의 패키지 루트·Groovy variant·설정 키 3건 오류; ArchUnit IDENTIFIER_ADAPTER_DOES_NOT_DEPEND_ON_OTHER_ADAPTERS_OR_BOOTSTRAP는 실재(confirmed)하고 .claude/hooks/ca_import_gate.py는 tracked 아님 | .claude/는 로컬 설정 영역이라 개발자 머신 존재 여부는 판정 불가 — clone 기준으로만 부재를 기록했다 |
| EVD-070 | 실행 probe | evidence/raw/140-identifier-negative-space-probes.txt (EXECUTION PROBE 절) | 2026-08-30 | normalize("1-1-1-1-1") → "00000001-0001-0001-0001-000000000001", "1-2-3-4-5" → "00000001-0002-0003-0004-000000000005" (canonical 아닌 입력을 수용해 재작성), "not-a-uuid"·무대시 32자·공백 포함은 IllegalArgumentException; normalize(null)→null / toUuid(null)·fromUuid(null)→NPE; newFileId·newUploadId 모두 version=4, UUID.randomUUID() version=4 | JDK 21의 UUID.fromString 동작에 의존하는 결과이며 다른 JDK 버전에서 관대 경로가 달라질 수 있다; 임시 test class는 실행 후 삭제하고 git clean 확인 |
| SRC-086 | module map / denominator | evidence/raw/141-fileserver-module-inventory.txt, src/adapter/outbound/fileserver/** | same revision | 119 tracked files(main 78 / 12,707 LOC, test 37 / 12,043 LOC, governance 4); 패키지 배치 루트 31 · platform/local 33 · verification 10 · security 2 · audit 2; 별도 source set·test lane 없음; leaf 밖 소비자는 app-bootstrap 하나 | 초기 sizing이며 각 sub-scope의 최종 denominator는 해당 manifest가 확정한다 |
| SRC-087 | config / activation | evidence/raw/142-fileserver-config-activation-probes.txt | same revision | 13/13 FULL_READ; R1/R2/플랫폼 세 namespace 분리와 rejectAmbiguous의 세 진입점 배치; 적재는 auto-configuration이 아니라 CaSkeletonApplication의 명시적 @ComponentScan(imports 파일 없음); R1은 ignoreUnknownFields 없음·상대 루트 허용·디렉터리 생성, R2는 전부 반대; README가 지목한 selector 기본값이 application.yml에 없음 | .claude·로컬 설정은 tracked 파일 기준으로만 판단했다 |
| SRC-088 | control plane / codec | evidence/raw/143-fileserver-control-plane-probes.txt | same revision | 6/6 FULL_READ(main 2,535 LOC); canonical 왕복 강제(decode 후 재encode 바이트 비교), 인접 전이 행렬과 terminal 종결성, SecureDirectoryStream 17회 vs R1 저널 0회, poison 래치의 root 범위와 읽기 허용이 test 이름으로 의도임을 확인; 세 타입 모두 package-private·leaf 밖 참조 0 | 후보 finding 3건을 코드·test로 추적해 결함 아님으로 판정했고 실행 probe는 돌리지 않았다 |
| SRC-089 | publication | evidence/raw/144-fileserver-publication-probes.txt | same revision | 26/26 FULL_READ; 19개 production 타입 전부 package-private·leaf 밖 참조 0; recoverR2가 상태별로 재개하고 producer를 재생하지 않음; 길이 프레이밍 canonical digest와 route token 충돌 컴파일 검사; R1/R2 엄격도 6축 대조와 두 계층 접점(decodeStoredOperation)이 엄격 경로를 쓰는지 확인 | R1/R2 격차는 문서가 선언한 상태이며 결함으로 올리지 않았다 |
| SRC-090 | platform/local IO | evidence/raw/145-fileserver-local-io-probes.txt | same revision | 30/30 FULL_READ; SecureDirectoryWalk의 서술자 상대 하강과 fallback 부재; platform/local의 Files.* 호출 전수 조사 → 쓰기 경로에 남은 5곳(AtomicMoveContentPublisher:53·113·114, ContentPublishVerification:53·114)과 그 유일한 보호가 모듈이 "a precheck could only ever approximate"라 적은 requireNoSymlinkBetween; TransferBufferPool.maxBorrowedBytes()의 소비자 0 | 발행 rename의 도달성은 스토리지 루트 쓰기 권한에 달려 있고, 그 루트 증명은 app-bootstrap 몫이라 이 leaf 범위에서 확정하지 않았다 |
| SRC-091 | verification / security / audit | evidence/raw/146-fileserver-verification-security-audit-probes.txt | same revision | 29/29 FULL_READ; AdminAuditPort·FileserverAuditPort·FileAccessPolicy·StorageHealthPort·OrphanScanPort·StorageUsageProbe·ReconciliationContentProbe 구현 8종과 app-bootstrap의 bean 생성 8곳을 확인해 README:105를 반증; 검증 사슬의 fail-closed 합성(timeout/예외 → RETRY, RETRY > ACCEPT); 인가 거부 메시지에 역할 미포함 | bean 생성 지점은 app-bootstrap 소스 기준이며 런타임 컨텍스트로 재확인하지는 않았다 |
| EVD-071 | 실행 probe | evidence/raw/146-fileserver-verification-security-audit-probes.txt (EXECUTION PROBE 절) | 2026-08-30 | inlineSafeProfile=false에서 ScriptableContentPolicy 9종 입력 판정: 평문 <script>·<html>·선행 공백·대문자·<svg>는 QUARANTINE, UTF-8 BOM + <html>·선행 HTML 주석 + <script>·NUL + <html>는 ACCEPT | String.stripLeading()의 JDK 동작에 의존하는 결과이며, 브라우저별 스니핑 차이는 검증하지 않았다; 임시 test class는 실행 후 삭제하고 git clean 확인 |
| SRC-092 | payload / CSV / testkit | evidence/raw/147-fileserver-payload-testkit-probes.txt | same revision | 15/15 FULL_READ; LocalPersistentPayloadOperations가 JDK에 서술자 상대 대응물이 없는 세 원시연산(createLink·createDirectory·force)을 javadoc에 선언하고 identity 검사로 감싼 것을 호출 전수로 확인; CSV 인코더의 세 상한과 수식 정책 3종; CrashRecoveryMatrixTest가 @EnumSource(CrashPoint.class)로 전 크래시 지점을 순회하고 두 발행 전략이 같은 ContentStoreContract를 상속 | testkit의 NFS·PVC fixture는 해당 환경이 없어 실행하지 않았다 |
| SRC-093 | module map / denominator | evidence/raw/149-objectstorage-module-inventory.txt, src/adapter/outbound/objectstorage/** | same revision | 206 tracked files(main 147 / 14,336 LOC, test 48 + resource 1 / 6,753 LOC, qualification source set 3종 6 files / 546 LOC, governance 4); 패키지 배치 s3 26 · control 24 · kernel 23 · config 19 · direct 13 · readiness 8 · maintenance 8 · codec 7 · filesystem 6 · multipart 5 · provider 4 · 루트 4; AWS SDK v2 BOM을 모듈 범위로 import; 레지스트리 allowed_dependencies=[application-core, shared-contract], runtime_memberships=[sample-portfolio] | 초기 sizing이며 각 sub-scope의 최종 denominator는 해당 manifest가 확정한다 |
| SRC-094 | governance / config / routing | evidence/raw/150-objectstorage-config-activation-probes.txt | same revision | 28/28 FULL_READ; app.object-storage는 기본 비활성이고 legacy alias와 혼용 시 예외; ObjectStorageProviderContribution이 describe(부작용 없음)와 create(부분 할당 정리 책임)를 분리; filesystem-local-dev가 production 프로파일에서 거부되나 판정이 prod/production 두 리터럴 소문자 비교; RoutingObjectReadAdapter의 무방비 split("\\.",-1)[1]은 ObjectReference 생성자 검증이 막아 결함 아님 | .claude·로컬 설정은 tracked 파일 기준으로만 판단했다 |
| SRC-095 | control plane / canonical JSON | evidence/raw/151-objectstorage-control-probes.txt | same revision | 25/25 FULL_READ(main 2,470 LOC); canonical 강제가 reader·writer·봉투 세 겹; 레코드 불변식이 값이 아니라 상태-증거 관계를 검증; 열거 API 부재로 키 공간 스캔이 표현 불가; 관용 UTF-8 디코딩 후보를 printable ASCII 검사로 추적해 결함 아님으로 판정 | zero-finding 결과이며 실행 probe는 돌리지 않았다 |
| SRC-096 | kernel / codec | evidence/raw/152-objectstorage-kernel-codec-probes.txt | same revision | 39/39 FULL_READ; 닫힌 상태 전이 행렬과 terminal 종결성, epoch fencing, pending effect / 응답 유실 화해; markEffectSent·markResponseLost가 current.updatedAt()을 그대로 넘겨 의도 시각과 유실 시각이 durable 레코드에 남지 않음 | 정적으로 결정 가능한 지점이라 실행 probe 불필요 |
| SRC-097 | s3 provider | evidence/raw/153-objectstorage-s3-probes.txt | same revision | 40/40 FULL_READ(main 3,581 LOC); AWS SDK 참조가 s3/** 16 + legacy 3에 갇히고 leaf 밖 production 유출 0(밖의 hit는 ArchUnit 금지 타입 카탈로그와 빌드 파일뿐); S3ClientPolicy가 재시도 최악 예산 ≤ 부모 호출 예산을 강제하고 평문 AWS 엔드포인트를 거부하며 자격증명을 [REDACTED]로; S3ProviderBinding이 AWS/MinIO에 반대 방향 신원 규칙을 강제하고 autoCreateBucket·publicAcl을 금지; S3ProviderErrorMapper가 mutation 불확실성을 INDETERMINATE, authoritative=false로 보존 | zero-finding 결과; 실제 AWS/MinIO 호출은 하지 않았고 정책·매핑의 정적 판정만 수행했다 |
| SRC-098 | direct transfer / multipart | evidence/raw/154-objectstorage-direct-multipart-probes.txt | same revision | 25/25 FULL_READ; requirePartSize의 세 호출 지점 중 DirectMultipartCoordinator:163만 finalPart=false 하드코딩이고 PartUploadGrantRequest에 마지막 part 표시 없음; validateSignedGrant가 upload 경로 1곳에만 있고 expectedExpiry는 미검사, planningEndpoint()는 정의상 항상 통과; coordinator·policy의 패키지 밖 참조 0이고 README가 "no direct-grant port is registered"로 선언하나 AWS binding은 DIRECT_* capability 주장을 통과시켜 presigner를 할당(MinIO는 거부) | 미배선 상태라 실행 probe 불가; 세 finding 모두 호출 인자·호출 부재·조립 경로로 정적 확정했다 |
| SRC-099 | filesystem / maintenance / readiness / provider / 루트 | evidence/raw/155-objectstorage-platform-readiness-probes.txt | same revision | 43/43 FULL_READ(main 30 / 2,420 LOC); readiness 레지스트리 forward reference 해소 — docs/registries/object-storage-readiness.yaml는 저장소 루트에 실재하고 build.gradle이 시스템 프로퍼티로 전달, leaf test가 9장 카드 집합·R1 두 장·R0 여섯 장을 강제; legacy-adoption.enabled=true, mode=APPLY는 설정으로 켜지는데 Ed25519LegacyAdoptionApprovalVerifier 생성 지점이 저장소 전체 0이고 승인자 키 설정 항목도 없음; ClaimResult가 발행을 막지 않음; filesystem-local-dev capability 표 2벌; legacy 루트에 production 프로파일 검사 없음 | 승인 검증기의 부재는 tracked 소스 기준이며, fork가 자체 bean을 공급하는 경우는 관측 범위 밖이다 |
| SRC-100 | qualification lanes | evidence/raw/156-objectstorage-qualification-lanes-probes.txt | same revision | 6/6 FULL_READ; 세 lane 모두 strict·non-skipping·requiredClasses 고정; 여섯 파일 중 provider를 실제로 호출하는 것은 MinioManagedObjectContractTest(digest 고정 MinIO에서 If-None-Match: * PUT과 CompleteMultipartUpload가 기존 객체를 덮고 stale If-Match만 412)와 MinioManagedObjectFaultTest(Toxiproxy 절단 → 5초 이내 유계 실패와 복구) 둘뿐; AWS lane 2종은 환경변수만 검사; provider 신원 문자열과 이미지 digest가 enum·version map·evidence JSON 세 곳에 독립 기재되고 교차 검사 없음 | lane 실행에는 Docker와 보호된 AWS sandbox 권한이 필요해 이 분석에서 실행하지 않았고, lane이 주장하는 내용과 그 소비처만 정적으로 추적했다 |
| EVD-072 | suite 검증 | evidence/raw/157-objectstorage-suite-verification.txt | 2026-08-30 | :adapter:outbound:objectstorage:test → classes=47 tests=140 failures=0 errors=0 skipped=0; git status --short 변경 0 | qualification source set 3종은 :test에 포함되지 않으며 Docker·AWS sandbox 권한이 필요해 실행하지 않았다 |
| SRC-101 | module map / denominator | evidence/raw/158-cache-redis-module-inventory.txt, src/adapter/outbound/cache-redis/** | same revision | 390 tracked files(main 316 / Java 314 · 32,082 LOC + resource 2, test 70 / Java 69 · 15,244 LOC + golden 1, governance 4); 자체 Redis SDK를 품은 leaf로 설계 문서의 다중 모듈 배치를 패키지 경계로 대체하고 RedisSdkModuleBoundaryTest가 강제; build.gradle이 spring-data-redis·micrometer 부재를 근거와 함께 선언하고 redisTopologyTest lane 4종에 mode allowlist·필수 클래스·최소 test 수·skip 0 게이트를 건다 | 초기 sizing이며 각 sub-scope의 최종 denominator는 해당 manifest가 확정한다 |
| SRC-102 | governance / config / 조립 | evidence/raw/159-cache-redis-config-activation-probes.txt | same revision | 26/26 FULL_READ; app.redis.enabled 하나가 전체 스위치이고 RedisSdkSettings가 @ConfigurationPropertiesScan 밖이라 "contributes nothing"이 문자 그대로 성립(test 4종); auto-configuration이 @Bean 7개(settings·validation·credentials·client·runtime owner·redisOptional·redisRequired)를 만들어 README의 "조립되지 않는다" 서술 중 셋을 반증; RedisStartupProbe/RedisCapabilityProbe의 production 호출자 0; raw allowlist 기본 리소스 부재는 startup 실패로 닫혀 있어 결함 아님 | 승인자 키·capability 설정은 tracked 소스 기준이며 fork의 자체 bean 공급은 관측 범위 밖 |
| SRC-103 | 타입 있는 명령 표면 | evidence/raw/160-cache-redis-api-surface-probes.txt | same revision | 83/83 FULL_READ; Expiration이 sealed이고 Persistent가 permit을 요구해 TTL 없는 쓰기가 표현 불가; permit/budget 요구를 4종으로 분류; "설계상 부재" 6건(KEYS·SETNX/SETEX/PSETEX·ZREVRANGE·RPOPLPUSH/BRPOPLPUSH·GEORADIUS·members())을 API·Lettuce 구현·명령 정책 yml 세 계층에서 대조(KEYS는 R4 BLOCKED); ApiParityTest가 sync/reactive 대칭을 반사로 강제하고 검사기 자신의 메타 test 보유; RedisOperations·ReactiveRedisOperations 구현 0 | 개별 표면 43종은 전부 구현돼 있으며 facade만 없다 |
| SRC-104 | 키 · 실패 · 명령 기술 · reactive | evidence/raw/161-cache-redis-key-error-command-probes.txt | same revision | 64/64 FULL_READ; 렌더된 키를 받는 API 부재를 sealed 계층과 renderer 단일 지점으로 확인; RedisFailureMetadata의 "모호 실행은 retryable 불가" 불변식과 storedDataCorruption 팩토리의 분리(실호출 2곳); RedisCommandDescriptor의 교차 필드 불변식 4종; requireIdentifier의 메일·전화 분기가 선행 문자 클래스에 가려 도달 불가이고 test는 타입만 검사; reactive getRange 누락 의심을 직접 diff로 오탐 판정 | 예외의 transient metadata는 직렬화 왕복 시 null이며 문서에 없다 |
| SRC-105 | gateway · request builder | evidence/raw/162-cache-redis-gateway-probes.txt | same revision | 95/95 FULL_READ(main 10,718 LOC); RedisCommandGateway가 114개 명령별 메서드로만 이루어지고 명령 이름을 받는 메서드 0; 11개 계열 전부 sync/reactive가 같은 *OperationRequests를 생성; RedisOperationContext가 R1 permit 검증·scan overshoot 허용(+512)·BLMOVE 이중 permit 처리를 한 곳에 모음; 응답 예산 강제 12곳; 구독 경로만 guard를 지나지 않고 그 대체 검사(네임스페이스·패턴 permit)가 실재; permit 정책 이름이 Java 18 + YAML 18 + 별도 상수 1로 흩어짐 | in-memory double은 implements로 114 메서드가 강제되므로 누락 의심은 오탐 |
| SRC-106 | guard · 연결 · 코덱 · 관측 | evidence/raw/163-cache-redis-guard-connection-codec-probes.txt | same revision | 44/44 FULL_READ; guard의 고정 순서 11단계와 두 건의 수정 이력(죽은 validateReply 제거, 발화 불가였던 다중 키 절 분리); 정책 문서를 일반 YAML 엔진으로 읽지 않는 이유와 그 좁은 파서; 레인이 계정을 함께 유도(SCRIPT→ADVANCED); RedisRuntimeOwner의 OPEN→DRAINING→CLOSED와 포화 시 거부; 두 실행자가 같은 협력자 4종; RedisCommandMetadataDiff("The build gate")의 main 참조 0 · lane 참조 0 · Gradle 태스크 0; 정책 문서 필드 표 11 vs loader allowlist 12 | drift gate의 비교 로직과 test 6종은 완성돼 있고 없는 것은 실제 서버 메타데이터를 넣는 연결이다 |
| SRC-107 | 스크립트 · 트랜잭션 · 확장 · raw · 클러스터 | evidence/raw/164-cache-redis-programmability-extensions-probes.txt | same revision | 54/54 FULL_READ; raw gateway가 카탈로그 RAW_ONLY 분류와 배포 승인 두 문을 모두 요구하고 토큰이 발급 레지스트리 인스턴스까지 검증; RawMovableKeys가 SORT/SORT_RO 한 형태만 파싱하고 BY/GET은 패턴이라 의도적으로 거부(test 8종); 스크립트 등록이 배포 단계이고 README의 EVALSHA→NOSCRIPT→SCRIPT LOAD 사슬이 forget(...) 호출로 실재; 그러나 NOSCRIPT 판정이 5벌이고 4벌이 레지스트리를 우회; 슬롯 검사 2곳은 범위가 달라 중복 아님 | 진입 타입 5종(raw gateway·transaction runner·admin·cluster observer/cursor)의 production 참조 0 |
| SRC-108 | 의미 포트 어댑터 | evidence/raw/165-cache-redis-semantic-adapters-probes.txt | same revision | 24/24 FULL_READ; CacheRegionPort·IdempotencyStorePortV2·DistributedLeasePort·EdgeRateLimitPort·ConnectionRegistryPort·EphemeralFanoutPort 6종 3,295 LOC 구현 확인(전용 test 5 + LiveRedisSemanticPortsTest)으로 README의 "그 코드는 이 leaf에 없다"를 반증; 포트별 실패 정책 대비(cache만 degrade, rate limit은 fail-closed, idempotency는 INDETERMINATE); 다섯 어댑터가 guard·executor·타입 API 참조 0이고 lease.gateway()를 직접 호출(30곳); CapabilityKeyspace가 requireRenderedSize를 적용하지 않는 두 번째 키 렌더 경로 | 현재 미배선이므로 즉각 노출은 없고, 키는 같은 RedisNamespace에서 조립되므로 네임스페이스 봉쇄만은 구성으로 유지된다 |
| EVD-073 | suite 검증 | evidence/raw/166-cache-redis-suite-verification.txt | 2026-08-30 | :adapter:outbound:cache-redis:test → classes=52 tests=435 failures=0 errors=0 skipped=0; git status --short 변경 0 | redisTopologyTest lane 4종은 excludeTags로 제외되며 실제 서버와 -Predis.topology.*를 요구해 실행하지 않았다 |
| SRC-109 | module map / denominator | evidence/raw/167-httpclient-module-inventory.txt, src/adapter/outbound/httpclient/** | same revision | 370 tracked files(main 260 / 15,004 LOC, test 62 / 6,049, testkit source set 35 / 2,754, httpClientPerformanceTest 7 / 495, jmh 2 / 130, governance 4); 설계의 19-모듈 배치를 패키지 경계로 대체하고 HttpClientModuleBoundaryTest가 강제; HTTP/3가 compileOnly인 이유·Jackson 3가 필수인 이유·testkit이 별도 source set인 이유·lane 둘이 failOnNoDiscoveredTests를 잃었던 기록이 build.gradle 주석에 있음; check에 hermetic lane 4종이 붙음 | 초기 sizing이며 각 sub-scope의 최종 denominator는 해당 manifest가 확정한다 |
| SRC-110 | profile / startup 검증 | evidence/raw/168-httpclient-profile-probes.txt | same revision | 35/35 FULL_READ; ClientProfileValidator가 34종 위반 코드를 결정적 정렬로 내고 각 코드가 막는 다운그레이드를 주석으로 적음(바인딩되지만 전송에 닿지 않는 설정 3종을 무시가 아니라 거부); app-bootstrap HttpClientStartupValidator:37이 실제 배선; ClientRuntimeRegistry.close()가 throw firstFailure를 스케줄러 종료보다 먼저 실행; POOL_ROUTE_EXCEEDS_TOTAL이 PoolSettings 생성자에 가려 도달 불가; 34종 중 test가 이름으로 잡는 것은 12종 | 위반 코드별 test 참조 계수는 test/testkit source set 전체 기준 |
| SRC-111 | 공개 API 어휘 | evidence/raw/169-httpclient-api-probes.txt | same revision | 55/55 FULL_READ; 증거 3축(ExecutionEvidence·AttemptStage.provesNotSent·BodyReplayability.weakest)과 OperationIdempotency가 D-09를 구성; HttpFailureMetadata가 제외 목록을 열거하고 HttpOperation·ObjectBody·IdempotencyKey가 각각 과거 유출을 근거로 toString을 재정의; TRACE 부재를 test가 반사로 확인; ObjectBody.deeplyImmutable의 instanceof Number가 AtomicInteger류 가변 타입을 통과시킴 | api/body 7종 중 값을 담는 둘만 toString 재정의가 필요함을 전수 확인 |
| SRC-112 | 재시도 자격 · 가드 파이프라인 | evidence/raw/170-httpclient-resilience-probes.txt | same revision | 47/47 FULL_READ(test 47 메서드); 결정표가 절대 차단 6 → 영구 → 증거 → 상태/실패 순으로 단조; 408/425/429가 멱등성 검사를 건너뛰던 수정 이력; AttemptResiliencePipeline이 회로 permission을 얻은 뒤 rate/bulkhead 거부 경로에서 반환하지 않음(releasePermission 저장소 전체 매치 0, bulkhead 경로는 rate 토큰만 반환); PARTIAL_RESPONSE 분기 도달 불가 의심을 전송 분류기 4종의 생산 지점으로 오탐 판정 | Resilience4j HALF_OPEN 시험 슬롯 소진은 라이브러리 의미론에 근거한 추론이며 실행 재현은 하지 않았다 |
| SRC-113 | 게이트웨이 · 응답 경계 | evidence/raw/171-httpclient-gateway-probes.txt | same revision | 46/46 FULL_READ; 와이어/디코드 두 예산과 읽는 도중 강제; RemoteProblemDecoder가 원격 status를 폐기하고 와이어 상태를 신뢰; BlockingRedirectCoordinator가 hop마다 allowlist 재적용·cross-origin 자격증명 제거·303 본문 폐기; BoundedDataBufferFlux의 doOnCancel·onErrorResume가 no-op; 리다이렉트 hop 상한은 RedirectEvaluator:16이 강제(오탐 판정) | 버퍼 누수를 주장하지 않았다 — no-op 연산자와 javadoc의 불일치만 기록 |
| SRC-114 | 보안 · 자격증명 | evidence/raw/172-httpclient-security-auth-probes.txt | same revision | 46/46 FULL_READ; 절대 URI를 정화가 아니라 거부; 멱등성 키가 실제로 헤더로 나가지 않던 수정("A duplicated payment is the shape of that bug"); HeaderPolicy의 소유 헤더 9종과 CR/LF 거부; SensitiveHeaderStripper의 "adds rather than replaces" 수정; auth record 5종 중 값을 담는 셋 모두 redacted toString; zero-finding | 가짜 메타데이터 편의 생성자는 production 호출자 0으로 확인 |
| SRC-115 | 동적 대상 · 관측 · 서비스 | evidence/raw/173-httpclient-service-dynamic-probes.txt | same revision | 56/56 FULL_READ; SSRF 사슬(정규화 → 전체 응답 검증 → thread-local 핀 → 전송 resolver 주입)을 호출 지점으로 전수 추적, app-bootstrap HttpClientTransportAutoConfiguration:81이 CallScopedDnsPin::addressesFor를 주입; HttpClientTagPolicy가 모르는 태그를 거부하고 쿼리 값은 통째로 폐기; 계약 lane의 메타 test 3종; ValidatedDnsResolver.approved 무경계 의심을 finally의 forget과 production 호출자 0으로 오탐 판정 | zero-finding |
| SRC-116 | 전송 6종 · testkit / perf / jmh | evidence/raw/174-httpclient-transport-testkit-probes.txt | same revision | 85/85 FULL_READ; TransportCapabilityValidator가 프로파일 요구와 전송 선언을 대조해 startup 거부; validatedDnsPinning 검사가 블로킹 오버로드에만 있고 리액티브에는 없음 — 주석이 "the two were being conflated"라고 지적한 상태가 한쪽에 잔존(현재 두 리액티브 전송은 두 플래그가 같아 노출 없음); testkit 계약 클래스 6종을 세 lane이 공유; 성능 lane 7종은 풀·재시도·회전·토큰경합·본문·H2를 재고 본문 재생 가능성 판정 비용은 재지 않음 | HTTP/3는 compileOnly라 Http3CapabilityReport가 클래스 부재 시 startup에서 거부 |
| EVD-074 | suite 검증 + 실패 진단 | evidence/raw/175-httpclient-suite-verification.txt | 2026-08-30 | :check는 src/gradle/archive-hygiene.gradle 게이트가 build/libs의 이전 리비전 JAR 2개를 발견해 실패(소스 무관, remedy 태스크 cleanStaleTraceableJars 존재, 이 분석은 삭제하지 않음); lane 5종 개별 실행 → test 283/3 failed, 나머지 4 lane 42 tests 0 failed, skipped 0; 실패 3건은 MutualTlsHandshakeContractTest의 expected: TLS_HANDSHAKE but was: CONNECT — ApacheFailureClassifier가 원인 사슬을 바깥부터 훑는데 CONNECT 분기가 TLS 분기보다 앞서 HttpHostConnectException이 안쪽 SSLHandshakeException을 가림; git status --short 변경 0 | hermetic test이고 의존성이 잠겨 있어 결정적으로 재현된다 |
| SRC-117 | module map / denominator | evidence/raw/176-outbound-messaging-module-inventory.txt | same revision | 69 tracked files(main 46 / Java 34 · 4,246 LOC + resource 12, test 19 / Java 16 · 3,670 LOC + resource 3, governance 4); build.gradle이 YAML·Jackson 2를 전 configuration에서 제외하고 verifyJsonSchemaRuntimeGraph를 check에 붙임; qualification lane 2종이 필수 클래스 목록과 함께 등록되고 루트 :prepareMessagingContractEvidence에 의존 | 초기 sizing |
| SRC-118 | 활성화 · 조립 | evidence/raw/177-outbound-messaging-activation-probes.txt | same revision | 14/14 FULL_READ; app.messaging.enabled(스위치)와 app.messaging.broker(선택자)의 분리와 그 이유; MessagingOffAutoConfigurationImportFilter가 spring.factories에 실제 등록되어 Boot의 Kafka/AMQP 자동설정 5종을 차단; 실행 probe: verifyJsonSchemaRuntimeGraph FAILED — 요구 좌표 tools.jackson.core:jackson-core:3.0.2 vs 잠긴 3.1.5; CompiledMessagingDescriptor의 leaf-main·app-bootstrap 참조 0이며 계약·목적지·봉투·스키마 4패키지를 leaf 밖에서 참조하는 파일 0 | 컴파일된 절반의 목적(증거 산출)은 build.gradle의 lane 구성에서 추론했고 문서에는 없다 |
| SRC-119 | 닫힌 JSON Schema 레지스트리 · 봉투 | evidence/raw/178-outbound-messaging-envelope-probes.txt | same revision | 21/21 FULL_READ; 어휘 allowlist 8종·닫힌 키워드 부분집합 5종($anchor·$dynamic*·$recursive*)·참조 사전 검사·핀 고정 메타스키마 9종; 실행 probe: authority.sha256의 9개 해시가 동봉 파일의 실제 SHA-256과 전부 일치; 봉투 작성이 원시 JSON 파서/생성기 API 없이 스냅샷 바이트를 삽입하고 가변 접근자를 한 번만 호출; 적대적 test 29 메서드가 파서·수·컬렉션·해시 경계를 이름으로 고정 | zero-finding |
| SRC-120 | 계약 컴파일 · 목적지 · 파티션 키 | evidence/raw/179-outbound-messaging-contract-destination-probes.txt | same revision | 13/13 FULL_READ; 열린 타입(raw·wildcard·Map·JSON 트리·인터페이스·제네릭 record 그래프)을 페이로드로 거부하고 기여 접근자를 정확히 한 번만 호출; 도메인 분리 상수 7종이 전부 버전 붙은 형태이고 4바이트 길이 프레이밍을 공유; 카탈로그 다이제스트가 입력 순서 독립; PartitionKeyV1이 교차 언어 벡터 진입점을 제공하고 골든 벡터 2종(비ASCII UTF-8 바이트 길이 포함) 보유 | zero-finding |
| EVD-075 | suite 검증 | evidence/raw/180-outbound-messaging-suite-verification.txt | 2026-08-30 | :adapter:outbound:messaging:test → classes=17 tests=92 failures=0 errors=0 skipped=0; :check는 verifyJsonSchemaRuntimeGraph에서 실패(게이트 자신의 버전 하드코딩); git status --short 변경 0 | qualification lane 2종은 루트 증거 파이프라인에 의존해 실행하지 않았다 |
| SRC-121 | 바인딩 컴파일 · 템플릿 카탈로그 | evidence/raw/183-notification-catalog-dispatch-probes.txt | same revision | 23/23 FULL_READ; digest 헬퍼가 문자열을 4바이트 길이 프레이밍으로 먹여 인접 필드 충돌을 구조적으로 배제; LocalEmailRenderer의 컨텍스트 인지 이스케이프 사슬(태그 27종 허용목록 → 토큰 문법이 컨텍스트를 요구 → 삽입 위치 검증 → 치환 시점 컨텍스트별 이스케이프 → quoteReplacement → 미해결 {{ 거부)을 전수 확인; 템플릿 자산은 manifest 체크섬 + 계획에 얼어붙은 체크섬·렌더러 리비전 이중 대조; validateRouteShape의 SINGLE 전용 가드(:141)가 switch(:159)보다 앞서 FAN_OUT_ALL·ORDERED_FALLBACK·default와 순환 탐지기 전체가 도달 불가이고 legacyReceiptUnsafeFallbackBoundsAndCyclesAreRejected가 hasMessageContaining("strategy")로 다른 가드에 걸려 통과 | 순환 탐지기는 정적으로 도달 불가를 증명했고 실행으로 반증하지는 않았다 |
| SRC-122 | 스케줄러 · 런타임 세대 · 시도 permit | evidence/raw/183-notification-catalog-dispatch-probes.txt | same revision | 30/30 FULL_READ; 실행 probe: 배경 작업자 3종(LeaseRecoveryService·ProviderEventReplayWorker·ReconciliationJobWorker)이 app-bootstrap NotificationPlatformWorkerConfig에 빈으로 등록되고 NotificationBackgroundWorkers.start()가 각각 scheduleWithFixedDelay — 배선 확인됨(cache-redis RedisStartupProbe 호출자 0과 대조); 상태 전이 7종을 형제로 비교해 markDraining/markDisabled만 current를 받고 쓰지 않음을 확인; AUTHENTICATION_FAILED → markDraining() → resumeHealthy()가 RegistryProviderRuntimeControl:30-39를 통해 관리자에게 노출되어 javadoc이 선언한 거부를 우회하고 원인 코드를 파괴; ProviderRuntimeStateTest:125-140이 세 전이를 각각 새 객체에서만 확인 | 우회는 정적 증명(무조건 덮어쓰기 3줄)이며 실행 재현은 하지 않았다 |
| SRC-123 | 렌더링 이스케이프 · 저장 시 암호화 | evidence/raw/184-notification-template-security-probes.txt | same revision | 32/32 FULL_READ; SecretPurpose 8종이 소유자 1:1이고 NotificationSecretRequirements가 전부 열거; AesGcmContactPointProtector가 두 키를 요구하고 keyId·자료 양쪽으로 동일성 거부, AAD에 접촉점 종류 결속, 키 256비트 강제; .auditRequired() 0건 · .purposeCode() 0건 — "Every reveal is auditable"를 선언한 AccessContext의 필드를 읽는 코드가 저장소에 없고 reveal은 null 검사만 함(감사 싱크 LoggingNotificationAudit은 존재하며 ProviderRuntimeRotator가 사용); Thymeleaf process( 2곳 중 catch는 :92 하나 — 프로덕션이 타는 mode-aware 오버로드(:80)는 무방비이고 CanonicalNotificationRenderer:125,133이 모드 있는 쪽만 호출 | 메시지 유출의 실제 문자열은 Thymeleaf 구현에 달려 있어 실행으로 확인하지 않았다 |
| SRC-124 | provider 포트 · SPI 라우팅 · 관측 | evidence/raw/185-notification-provider-core-probes.txt | same revision | 38/38 FULL_READ(main 29 + test 9, probe가 카운트 확인); Retry-After 힌트가 NotificationDispatchService:381 → RetryBackoff:44-45로 도달하고 계산값보다 길 때만 채택된 뒤 max로 상한 — javadoc 주장과 일치, 회로 닫힘; RoutingNotifier가 채널 내 providerId 중복과 미등록 라우트를 생성자에서 거부하고 런타임 미바인딩은 AdapterDisabledException; 첨부 무결성이 AttachmentIntegrityGuard.resolve 안에서 크기·다이제스트를 MessageDigest.isEqual로 대조; NotificationHealthReporter가 unhealthy로 보는 4조건에 DRAINING이 없어 SRC-122의 우회가 헬스 신호도 함께 끔; 음수 Retry-After가 ProviderFailure 생성자에서 IllegalArgumentException | 음수 헤더는 RFC 비준수 provider를 전제하며 실행 재현하지 않았다 |
| SRC-125 | provider 구현 8종 · SigV4 · SNS · RFC 8291 | evidence/raw/186-notification-provider-impl-probes.txt | same revision | 76/76 FULL_READ(main 60 + test 16, probe가 카운트 확인); requireExternallyRoutable의 프로덕션 호출처는 SES·webhook 둘뿐이고 가드 javadoc이 지목한 "Web Push endpoints and webhook targets"와 다름 — WebPushSubscriptionValue:50-57이 약한 스킴 검사의 private 사본을 들고 있어 grep으로도 드러나지 않으며 EndpointGuardCallSiteTest에 WebPush 언급 0; boundedBody가 BodySubscribers.ofByteArray()를 upstream으로 써서 전부 읽은 뒤 mapping으로 자름 — 주석의 "not ofByteArray()"와 반대; SigV4가 getHost()(포트 없음)를 서명하고 JDK는 포트 포함 Host를 보냄; AwsSignatureV4Signer:117-119가 비밀을 String으로 승격(leaf 내 유일); SNS SignatureVersion 1(SHA-1)을 발신자가 선택 가능하고 v2 강제 설정 없음 | Web Push SSRF는 이 템플릿에 인바운드 등록 경로가 동봉되지 않아 현 상태로는 미도달 — 포크가 붙이는 순간 통과된 상태가 된다 |
| SRC-126 | SPI 기여 2종 · 계약 testkit | evidence/raw/187-notification-spi-testkit-probes.txt | same revision | 19/19 FULL_READ(main 6 + test 9 + resources 4); ProviderFaultHarness가 목이 아닌 실제 JDK HTTP 서버 소켓을 띄워 "본문 기록 후 연결 절단"을 재현; PiiLeakScanner가 패턴이 아니라 정확한 픽스처 값을 탐색; 성능 lane이 처리량이 아니라 규모 무관 성질만 게이트; ProviderResults.fromTransport 호출 어댑터 6종에 FCM이 없고 FcmBatchCoordinator가 gateway.sendBatch를 try 없이 호출 — "커밋 후 응답 손실 = ambiguous" 규칙 밖의 유일한 provider이며 배치라 한 번의 손실이 배치 크기만큼 영향; extends ProviderAdapterContract 3/8, ContractAdapters 등록 5/8, FCM 테스트에 AMBIGUOUS 0건 — 두 계약 집합이 모두 비껴간 provider가 계약을 만족하지 않는 provider | FCM 전송 실패의 실제 예외 타입은 포크가 넣는 FcmGateway 구현에 달려 있다 |
| EVD-076 | suite 검증 | evidence/raw/187-notification-spi-testkit-probes.txt | 2026-08-30 | :adapter:outbound:notification:test → BUILD SUCCESSFUL, GRADLE_EXIT=0; 이 모듈의 발견 7건(P2)은 모두 테스트가 통과하는 상태에서 나왔다 — 두 건(SRC-121·SRC-122)은 통과하는 테스트가 다른 이유로 통과하거나 합성을 확인하지 않은 경우 | :check는 실행하지 않았다(httpclient에서 확인된 archive-hygiene 스테일 JAR 게이트가 소스와 무관하게 실패하며, 이 분석은 build 산출물을 삭제하지 않는다) |
| SRC-127 | module map / denominator / 소스셋 | evidence/raw/188-inbound-web-module-inventory.txt | same revision | 638 tracked files이 여섯 소스셋으로 갈림(main 400 · test 150 · testkit 54 · webfluxContractTest 16 · jettyCompatTest 9 · nginxProxyTest 5 · governance 4); main Java 27,473 LOC · test Java 18,319 LOC · main 패키지 74개; build.gradle이 각 소스셋 분리의 근거를 "그렇게 하지 않으면 레인이 무엇을 인증하게 되는가"로 적음(Jetty 레인이 Tomcat 위에서 돌 위험 · 리액티브 게이트가 서블릿 스택을 인증할 위험 · Docker 없는 check가 @Disabled로 귀결될 위험) | 초기 sizing; 12개 sub-scope 분할은 이 트리에서 기계 계산 |
| SRC-128 | 패키지 도달성 지도 | evidence/raw/192-inbound-web-package-reachability.txt | same revision | main 74개 패키지 각각에 대해 (a) 다른 web main 패키지가 import하는 수 in, (b) app-bootstrap/sample-portfolio가 import하는 파일 수 ext를 기계 산출. security in=0 ext=0(11파일) · cache in=0 ext=0(4) · advanced/* 대부분 in=0 ext=0 · fileserver.*만 ext>0가 다수. 이 지도가 SS3SS11의 도달성 판정 기준선 | import 기반이므로 리플렉션·컴포넌트 스캔 경로는 별도 확인 필요(각 sub-scope에서 수행) |
| SRC-129 | 거버넌스 · 모듈 경계 강제 | 7로 배선; 설계 §10의 5계층 예산 중 요청 계층만 강제(evidence/raw/189-inbound-web-governance-probes.txt | same revision | 51/51 FULL_READ; 다섯 커스텀 레인의 Gradle 참조 0, CI 워크플로 다섯 파일이 전부 호출 — 회로는 YAML에서 닫힘; WebStableModule(539줄 enum)이 모듈 id·패키지·순도·허용 edge를 선언하고 WebModuleBoundaryTest가 실제 트리를 스캔해 양방향 대조(긍정 5규칙 + 부정 픽스처 4개 + 빈 스캔 거부); 프레임워크 탐지 정규식에 Jackson 2·3 병기("a hole in exactly the check that is supposed to have none"); CorsSettings의 contains("*")가 setAllowedOrigins 소비처와 정확히 짝 | 레인 실행은 하지 않음 |
| SRC-130 | 에러 계약 이중화 | evidence/raw/190-inbound-web-error-probes.txt | same revision | 33/33 FULL_READ; 두 @RestControllerAdvice가 같은 컨텍스트에 등록되어 다섯 프레임워크 예외에서 problem+json이, 나머지 22종에서 Envelope이 나간다(WebMvcProblemExceptionHandler @Order(HIGHEST_PRECEDENCE+10) vs 무순서 GlobalExceptionHandler); README:168이 "D5: RFC 7807 ProblemDetail 표현은 거부"를 선언하고 problem+json/RFC 9457/ProblemCode 언급 0; leaf의 어떤 테스트도 두 advice 를 함께 세우지 않으며 NoResourceFoundErrorHandlingTest는 이기는 쪽을 @Import에서 빼고 지는 쪽을 단언; WebProblemSanitizer.alreadySafe 호출자 0이고 내부 삼항도 도달 불가 | 두 advice 공존 시의 실제 응답은 정적 추론(순서 규칙)이며 실행 재현하지 않음 |
| SRC-131 | 신원 · 요청 컨텍스트 배선 | evidence/raw/191-inbound-web-security-probes.txt | same revision | 44/44 FULL_READ; WebMvcRequestContextHolder.store() 호출자 저장소 전체 0이고 자동설정이 등록한 argument resolver는 require()로 항상 throw; new WebRequestContext( main 유일 지점이 WebFluxRequestContextFilter:81이며 ActorContext.anonymous()·TenantContext.none()·Locale.ENGLISH·ApiMajorVersion(1) 넷을 상수로 채움; security 패키지 11파일이 서로만 참조(WebSecurityContextBridge main_refs=0, AuthenticationView 생성은 테스트뿐), 교차 테넌트 가드 rejectTenantInput이 그 섬 안에만 존재; publicPaths permitAll이 RestrictedPathRule보다 먼저 등록됨 | 관리자 2단계 우회(§12.4의 auth-mode 철자)는 Spring @ConditionalOnProperty의 equalsIgnoreCase 동작에 대한 정적 추론 |
| SRC-132 | 용량 보호 계층의 등록 지점 | evidence/raw/193-inbound-web-capacity-probes.txt | same revision | 50/50 FULL_READ; WebMvcBudgetFilter·WebFluxBudgetFilter·WebMvcThrottleFilter·WebFluxThrottleFilter·SemaphoreAdmissionController 다섯 전부 픽스처 애플리케이션에서만 생성(testkit/webtestkit/BudgetFixtureApplication:43 등), main·app-bootstrap 등록 0; WebBudgetCatalog는 두 자동설정이 만들고 읽는 코드 0; backend.web.budgets 문자열이 자바 한 줄에만 존재해 예외 핸들러는 기본 꺼짐이고 켜면 BudgetProblemMapper 빈 부재로 부팅 실패; 배선된 속도 제한은 RateLimitWebConfig의 MVC 인터셉터 하나(APP_RATE_LIMIT_ENABLED:false) | 리액티브 속도 제한 부재는 인터셉터가 WebMvcConfigurer라는 사실에서 도출 |
| SRC-133 | 멱등성 · durable operation 조립 | evidence/raw/194-inbound-web-idempotency-probes.txt | same revision | 50/50 FULL_READ; WebIdempotencyGate·두 invoker·IdempotentResponseWriter·SemanticRequestFingerprintFactory 전부 test/testkit에서만 생성, app-bootstrap의 web 멱등성 참조 0(그쪽 bootstrap/idempotency/*는 애플리케이션 계층 PostgreSQL 제공자); 두 durable-operation 컨트롤러가 app.web-platform.durable-operations.enabled로 게이트되나 그 문자열이 yaml에 없고 OperationQueryService 빈도 없음; 의미 지문이 U+001F 구분자 기반이고 길이 프레이밍이 아님 | 지문 충돌은 구성 가능성만 확인, 실제 충돌 생성은 하지 않음 |
| SRC-134 | 표현 계층(페이지네이션·조건부·캐시·버전) | evidence/raw/195-inbound-web-representation-probes.txt | same revision | 54/54 FULL_READ; 다섯 패키지 중 소비 모듈이 실제로 부르는 것은 ETags 하나(sample-portfolio WorkLogController 3곳); filter/CacheControlFilter(@Component, 24줄)가 모든 응답에 Cache-Control: no-store를 붙여 같은 컨트롤러의 ETag/If-None-Match 304 경로를 규격상 무력화하고, 그것을 조정하도록 설계된 cache 패키지 310 LOC은 패키지 밖 참조 0; UnsupportedApiVersionException은 main throw 지점 0 | no-store와 조건부 읽기의 충돌은 RFC 9111 해석에 근거하며 브라우저 실동작은 확인하지 않음 |
| SRC-135 | JSON 강건화 · 코덱 · OpenAPI | evidence/raw/196-inbound-web-codec-probes.txt | same revision | 45/45 FULL_READ; WebJsonProfile 8개 필드 중 7개는 BoundedJsonFactory/WebObjectMapperFactory가 강제하고 maxArrayElements만 독자 0 — Jackson 3 StreamReadConstraints에 배열 원소 상한이 없고 매퍼도 검사하지 않음, §16.1의 바이트 예산 부재와 겹쳐 배열 원소 수 상한이 어느 계층에도 없음; maxStringBytes가 Jackson의 문자 기준 maxStringLength에 매핑; SecureXmlInputFactory가 DTD·외부 엔티티를 끄고 거부 리졸버까지 검(secure() 자가검사 포함); 배선된 OpenApiCustomizer는 config/OpenApiContractConfig의 익명 람다 하나이고 openapi 패키지 607 LOC은 빈이 되지 않음 | XML/CBOR은 compileOnly로 런타임 부재가 의도된 설계 |
| SRC-136 | 필터 체인 · 관측 · 프록시 신뢰 | evidence/raw/197-inbound-web-observability-probes.txt | same revision | 53/53 FULL_READ; 배선된 필터 다섯(MVC 자동설정 2 + @Component 2 + WebFlux 자동설정 1); WebMvcRequestIdFilter(기본 trustInboundRequestId=false, 순서 HIGHEST_PRECEDENCE+10)가 UUID를 쓴 뒤 RequestLoggingFilter(무순서 → LOWEST_PRECEDENCE)가 클라이언트 헤더 값으로 응답 헤더·MDC를 덮어씀; HeaderSanitizer가 <0x20을 제거해 로그 인젝션은 아님; proxy 패키지 421 LOC 미배선이고 스푸핑 방어는 nginxProxyTest/resources/nginx/proxy_headers.conf가 location마다 헤더를 덮어쓰는 데 의존; server.forward-headers-strategy 기본값이 framework | 프록시 우회 도달 가능성은 배포 토폴로지에 의존하며 이 분석에서 확인하지 않음 |
| SRC-137 | Advanced 능력 카탈로그와 게이트 | evidence/raw/198-inbound-web-advanced-probes.txt | same revision | 65/65 FULL_READ; WebAdvancedFeature 상수 11개, advanced/**의 프로덕션 @ConditionalOnProperty 접두사 2개(mvc-virtual-threads · ndjson) — 나머지 9개 능력은 프로퍼티도 @Configuration도 빈도 없음; WebAdvancedFeatureFlags(단일 활성화 표면으로 설계) 프로덕션 독자 0; VirtualThreadProfile.propertyName()이 virtual-threads(=mvc- 누락)를 반환하고 호출자 0; ndjson 스위치 하나가 NDJSON과 JSON_SEQUENCE 둘을 켬 | 능력이 off-by-default인 것은 build.gradle이 명시한 설계 |
| SRC-138 | fileserver 조립 · 리액티브 활성화 조건 | evidence/raw/199-inbound-web-fileserver-probes.txt | same revision | 73/73 FULL_READ; 이 leaf에서 유일하게 완전히 조립된 하위 트리 — FileserverPlatformAutoConfiguration이 URI 매퍼·다운로드 전략·요청 컨텍스트 팩토리를 만들고 FileserverStartupConfiguration:87이 attestMapping()을 시작 시 호출; DefaultNginxInternalUriMapper가 앵커 정규식 + 구성 후 ..////\ 재검사; @ConditionalOnWebApplication(REACTIVE)가 걸린 29개 main 파일은 클래스패스가 SERVLET을 고정하므로 활성화 불가(leaf build.gradle이 spring-boot-starter-web 선언 · app-bootstrap lockfile에 tomcat/webmvc · sample-portfolio도 starter-web · setWebApplicationType main 사용 0) | WebApplicationType.deduceFromClasspath() 동작에 근거한 정적 판정 |
| SRC-139 | notification 웹 표면 · admin | evidence/raw/200-inbound-web-notification-admin-probes.txt | same revision | 26/26 FULL_READ; CallbackRequestConfiguration이 게이트 아래에서 자기 의존을 @ConditionalOnMissingBean으로 공급하고 신뢰 프록시 기본값이 빈 집합("Honouring them unconditionally would let any caller choose the URL that gets signature-verified") — 닫힌 옵트인; SpringMvcRouteInventoryCollector(138줄)는 저장소 전체 참조가 자기 파일 2줄뿐(테스트도 0); WebPlatformStartupValidator(62줄)는 test 5 · main/boot 0으로 시작 시 실행되지 않음(fileserver의 attestMapping()과 대조) | — |
| SRC-140 | testkit · 세 런타임 계약 레인 | evidence/raw/201-inbound-web-testkit-probes.txt | same revision | 94/94 FULL_READ; 계약 클래스 7종이 소스셋 분리와 dependsOn으로 세 런타임에 강제 적용(notification의 상속 3/8과 대조); WebArchitectureRules 7규칙이 app-bootstrap WebProductionArchitectureTest:47에서 프로덕션 트리에 적용되고 WebArchitectureRulesTest:86-88이 개수를 고정; 픽스처 애플리케이션 9개가 new로 세우는 플랫폼 타입 목록이 §16.1·§20.1·§36.1의 미배선 목록과 일치 — 레인이 인증하는 조립은 픽스처의 조립 | — |
| EVD-077 | suite 검증 | analysis/14-adapter-inbound-web.md §50.6 | 2026-08-30 | :adapter:inbound:web:test + :webSecurityBoundaryTest → BUILD SUCCESSFUL, GRADLE_EXIT=0, classes=176 tests=1221 failures=0 errors=0 skipped=0; 이 모듈의 P1 6건·P2 8건 중 테스트가 검출한 것은 0건; git status --short 변경 0 | webCrossStackParityTest·webJettyCompatTest·webFluxContractTest·webNginxProxyTest·webAdvancedTest는 실행하지 않음(임베디드 서버 2종 다운로드 · Docker 런타임 요구) |
| SRC-141 | 컴포지션 루트 스캔 경계 | evidence/raw/203-composition-root-scan-boundary.txt | same revision | CaSkeletonApplication.AUTO_CONFIGURED_PACKAGES 정규식이 web leaf의 다섯 패키지(mvc.error · mvc.budget · mvc.operation · webflux.error · webflux.operation)를 컴포넌트 스캔에서 제외하고 javadoc이 그 이유를 "Ownership by auto-configuration is what ties a control's presence to its dependency's"로 적음; 그 소유권을 넘겨받는 자동설정이 없음 — AutoConfiguration.imports 2줄 중 어느 것도 해당 타입을 만들지 않고, app-bootstrap의 해당 타입 참조 0, .imports/.factories 참조 0, WebProblemFactory 참조 0. 이 사실이 모듈 14 §8.1의 판정을 "두 계약 공존"에서 "RFC 9457 계약 23파일 미등록"으로 교체 | 정적 판정(정규식 · 등록자 부재); 실제 컨텍스트를 띄워 빈 목록을 확인하지는 않음 |
| SRC-142 | module map / denominator | evidence/raw/202-inbound-grpc-module-inventory.txt | same revision | 18 tracked files(main 8 · test 6 · governance 4), main Java 602 LOC · test Java 782 LOC — 단일 bounded scope; build.gradle이 third-party grpc starter 없이 SmartLifecycle이 Netty 서버를 직접 소유하는 이유, .proto/protobuf 플러그인 부재, grpc-bom/protobuf-bom을 모듈 스코프에서 import해 strict-locking blast radius를 이 모듈에 가두는 이유를 명시; registerStrictQualificationTest가 두 클래스를 이름으로 요구 | 초기 sizing |
| SRC-143 | gRPC 전송 계약 · 활성화 · 에러 매핑 | evidence/raw/204-inbound-grpc-probes.txt | same revision | 18/18 FULL_READ; 활성화 삼중 게이트 — @ConditionalOnProperty(matchIfMissing=false) + @AssertTrue isInsecureLocalConfigurationValid()(!enabled || (allowInsecureLocal && InetAddress.isLoopbackAddress())) + feature 서비스 존재 시 정확히 하나의 GrpcAuthenticationPolicy 요구; GrpcExceptionHandlingInterceptor가 네 실패 경로(handler throw · listener throw · onError · raw status)를 하나의 sanitizing close로 모아 호출자 description·트레일러를 폐기하고 code/category 트레일러로 재작성; GrpcStatusMapper.toStatus가 Category 10값을 default 없이 전수 처리; errorCodeOf의 종료 조건이 getCause() == current 자기참조 검사뿐이라 2-순환에서 무한 루프 — 저장소 전체 9개 순회 지점 중 5개는 깊이 제한, 4개(grpc · MvcDisconnectDetector · WebFluxDisconnectDetector · TransactionRetryClassifier)는 자기참조 검사이며 JdkNotificationHttpGateway:93-97이 그 2-순환 사례를 이름으로 적고 깊이 제한을 택한 근거를 남김; BindableService·GrpcAuthenticationPolicy 구현 0 · ca-skeleton.grpc yaml 키 0은 CLAUDE.md가 선언한 상태 | 순환 사슬은 구성 가능성만 확인, 실제 무한 루프 재현은 하지 않음 |
| EVD-078 | suite 검증 | analysis/15-adapter-inbound-grpc.md §5 | 2026-08-30 | :adapter:inbound:grpc:test + :grpcTransportQualificationTest → BUILD SUCCESSFUL, GRADLE_EXIT=0, classes=8 tests=48 failures=0 errors=0 skipped=0; qualification lane이 grpcTransportQualificationTest: 15 tests, 0 skipped 증거를 출력; GrpcP1BoundaryWireTest가 실제 loopback ephemeral Netty 서버로 와이어 계약을 확인 | — |
| SRC-144 | module map / denominator | evidence/raw/205-inbound-graphql-module-inventory.txt | same revision | 534 tracked files(main 411 · test 103 · testFixtures 16 · governance 4), main Java 26,303 LOC · test Java 13,671 LOC, main 패키지 41개; 11개 sub-scope 분할을 패키지 트리에서 기계 계산(중복 0 · 미할당 0) | 초기 sizing |
| SRC-145 | 패키지 도달성 지도 | evidence/raw/206-inbound-graphql-package-reachability.txt | same revision | main 41개 패키지의 in(다른 graphql main 패키지가 import) / ext(app-bootstrap·sample-portfolio가 import) 기계 산출 — ext 열이 전 패키지 0이며, 이는 컴포지션 루트가 dev\.caskeleton\.adapter\.inbound\.graphql\..*를 컴포넌트 스캔에서 제외하고 조립을 자동설정 진입점 하나에 맡긴 구조와 일치 | import 기반; 자동설정 @Bean 참조는 별도 삼중 카운트로 확인 |
| SRC-146 | 조립 진입점 · off 계약 | evidence/raw/207-inbound-graphql-autoconfigure-probes.txt | same revision | 60/60 FULL_READ; .imports 한 줄이 마스터 게이트를 든 얇은 루트(GraphQlRootAutoConfiguration)이고 704줄 플랫폼 설정(39 @Bean · 43 @ConditionalOn)을 @Import; spring.factories가 AutoConfigurationImportFilter(프레임워크 GraphQL 자동설정 10개를 이름으로 차단)와 EnvironmentPostProcessor(은퇴 키 거부 + 콘솔 플래그 기본값 기여)를 건다; off 계약의 두 절반이 app-bootstrap GraphQlShippedAndGatedTest(빈 인벤토리 + 실제 포트에서 미매핑 경로와 상태코드 동일성)로 검증됨; HealthGraphqlController가 @Import에 있고 그 주석이 "no root imported it ... Its own tests passed throughout by registering the class themselves"로 과거 결함을 기록 — 모듈 14 §8.1과 같은 형태를 여기서는 닫음 | 프레임워크 자동설정 목록은 하드코딩이며 새 항목 추가에 대한 드리프트 검사는 없음 |
| SRC-147 | 스키마 거버넌스 · 스칼라 · 호환성 | evidence/raw/208-inbound-graphql-schema-probes.txt | same revision | 46/46 FULL_READ; 파일 단위 삼중 카운트로 GraphQlScalarWiringConfigurer(7) · GraphQlScalarManifest(4) · GraphQlMappingInspectionGate(3) 배선 확인; GraphQlSchemaAssembler·GraphQlSchemaContract·GraphQlOneOfSchemaGate·GraphQlOneOfInputValidator autoconf=0 main_other=0이고 GraphQlSchemaHash 생산 사슬(assemble → AssemblyResult.schemaHash)의 유일한 소비자 GraphQlPlatformActuatorEndpoint도 @Bean이 없음; graphql-java 25.0이 @oneOf를 자체 처리 | 조립 순서 불안정의 실제 발현은 조각이 하나뿐이라 관측 불가 |
| SRC-148 | 실행 사슬 · 요청 컨텍스트 · 예산 계층 | evidence/raw/209-inbound-graphql-execution-probes.txt | same revision | 60/60 FULL_READ; runtime 19종 대부분이 autoconf 2GraphQlPlatformWebInterceptor:135 + GraphQlRequestContext.withDeadline 단조 조이기 + GraphQlCancellation) 되고 GraphQlDeadlinePropagator의 파생 다섯 메서드는 호출자 0 — GraphQlTimeoutPolicy·GraphQlResolverBudget 참조자가 전부 미배선 클러스터 내부; 익명 연산 거부는 배선된 GraphQlOperationSelectionHandler가 네 가지 케이스로 수행 | 다운스트림 데드라인 미전달의 실제 영향은 아웃바운드 어댑터 기본값에 의존 |
| SRC-149 | 비용 제어 · 정책 · 보안 | evidence/raw/210-inbound-graphql-cost-security-probes.txt | same revision | 57/57 FULL_READ; 구조 한계·복잡도·관측은 배선(autoconf 46); 6으로 배선 | 프레임워크가 GraphQL-over-HTTP 스펙을 구현하므로 동작 자체는 합리적 |
| SRC-151 | DataLoader · 커서 · 뮤테이션 | GraphQlParserOptionsFactory(파서 한계를 graphql-java 정적 전역에 설치) 호출자 0 — backend.graphql.limits.* → GraphQlClientPolicy → GraphQlParserLimits.from(...) 사슬이 끊김; GraphQlClientPolicyManifest 미배선이고 자동설정이 GraphQlClientPolicy.defaults(properties) 단일 빈을 8곳에 주입 — 자격에서 해석된 프로파일이 예산을 고르지 않음; GraphQlContextPropagator는 네 진입점 전부 finally 복원으로 누수 없음 | graphql-java 기본 파서 한계가 백스톱으로 작동 |
| SRC-150 | HTTP 전송 계약 · 오류 · 관측 | evidence/raw/211-inbound-graphql-http-probes.txt | same revision | 48/48 FULL_READ; main 전체에 GraphQlHttpHandler/RouterFunction/@PostMapping이 없어 이 leaf는 HTTP 엔드포인트를 소유하지 않음 — /graphql은 Spring GraphQL이 발행; http 19파일 중 값으로 소비되는 둘(GraphQlHttpProfile 2 · GraphQlJsonStructurePolicy 4)을 뺀 전송 기계는 닫힌 섬; GraphQlRequestErrorMapper(파싱·검증 실패 매퍼) 미배선; 관측 9종은 autoconf 3evidence/raw/212-inbound-graphql-data-probes.txt | same revision | 69/69 FULL_READ; dataloader는 GraphQlBatchLoaderRegistrar(autoconf=4) 경유로 배선; backend.graphql.cursor.key-ids를 읽는 프로덕션 코드가 시작 검증기와 액추에이터 둘뿐이고 서명하는 코드가 없음 — HmacGraphQlCursorCodec·GraphQlCursorKeyRing autoconf=0 main_other=0; 이 사실을 autoconfigure/GraphQlPolicyRequestPathTest(GQL-INT-003)가 javadoc으로 기록하고 "this test fails the moment somebody wires one half without the other"로 고정 | 페이지네이션이 어떤 feature에도 붙지 않아 현재 조작 대상 커서 자체가 없음 |
| SRC-152 | capability 등급표 대조 | evidence/raw/213-inbound-graphql-release-probes.txt | same revision | 10/10 FULL_READ; CLAUDE.md가 4등급(modelled/wired/integration-verified/production-verified)을 정의하고 "현재 등급보다 높게 표현하지 않는다"를 규칙으로 선언, 13행 중 일곱을 스스로 modelled로 강등; sub-scope 0206의 파일 단위 배선 데이터와 13행을 전수 대조한 결과 12행 일치, 요청 크기/Accept 협상 (http/) 한 행만 불일치 — 인용된 두 증거(GraphQlRequestBoundsTest·GraphQlAcceptNegotiationTest)가 endpoint 테스트가 아닌 순수 단위 테스트이고 대상 타입은 autoconf=0; GraphQlStableCapabilityManifest.STABLE이 SIGNED_CURSOR_CONNECTION을 포함해 등급표(modelled)와 불일치 | 등급표는 사람이 읽는 문서, 매니페스트는 requireStable이 소비하는 기계 판정 |
| SRC-153 | Advanced 3개 sub-scope | evidence/raw/214·215·216-inbound-graphql-advanced-*-probes.txt | same revision | 163/163 FULL_READ(51+53+59); 141개 Advanced main 파일 전부 autoconf=0이고 등급표의 modelled 선언과 일치; 타입 이름이 등급을 인코딩(*Admission — "Spring transport handler 는 없다(그래서 타입 이름도 *Admission 이다)"); *HandlerFactory 세 종은 "Decides whether the handler may exist, and on what terms"로 판정만 수행; advanced/springdata가 UNSUPPORTED로 강등되며 "a capability flag cannot make an architectural rule conditional" 근거 기록; GraphQlAdvancedFeatureFlags가 @ConfigurationProperties가 아니라 정적 팩토리만 가져 활성화 설정 표면이 없음 | Advanced 진입점이 .imports에 없음 — 등급표는 이를 modelled로 인정 |
| EVD-079 | suite 검증 | analysis/16-adapter-inbound-graphql.md §45.4 | 2026-08-30 | :adapter:inbound:graphql:test → BUILD SUCCESSFUL, GRADLE_EXIT=0, classes=186 tests=1603 failures=0 errors=0 skipped=0 | graphqlStableTest(605) · graphqlContractTest(9) · graphqlAdvancedTest(152) 세 플랫폼 레인은 실행하지 않음 |
| SRC-154 | module map / denominator | evidence/raw/218-inbound-websocket-module-inventory.txt | same revision | 253 tracked files(main 169 · test 67 · testkit 7 · nginxWebSocketTest 4 · jettyWebSocketTest 1 · brokerRelayTest 1 · governance 4), main Java 12,784 LOC · test Java 9,435 LOC, main 패키지 39개; META-INF 자동설정 리소스 없음 — 조립이 전적으로 컴포넌트 스캔에 달림 | 초기 sizing |
| SRC-155 | 세 설정 네임스페이스와 조립 지점 | evidence/raw/219226-inbound-websocket-*-probes.txt | same revision | 253/253 FULL_READ; 169개 main 파일 중 Spring 애노테이션을 가진 것이 7개이고 설정 접두사가 셋으로 갈림 — ca-skeleton.websocket.*(stomp/WebSocketConfig가 소비, 실제 동작) · app.websocket-platform.advanced.*(4개 @Configuration) · backend.websocket.*(WebSocketPlatformSettings, 소비 @Configuration 0); 세 접두사 모두 어떤 application.yml에도 없음; WebSocketPlatformStartupValidator(125)와 WebSocketStackExclusivity(78) 프로덕션 호출자 0 — 후자는 inbound-web §40.1(서블릿/리액티브 이중 스택에서 리액티브 엔드포인트가 조용히 응답하지 않는 상태)을 이름 붙여 탐지하는 클래스; CLAUDE.md Responsibility 5줄·Typed settings 4키가 stomp 8파일만 서술하고 Evidence 절의 면책("Broker relay, multi-node/durable delivery, rollback-safe publication, replay/resume, backpressure ... are not claimed")이 advanced/stomp/rabbit(7)·cluster(9)·resume(8)·outbound(8)를 덮되 90개 플랫폼 파일은 덮지 않음 | evidence 파일의 autoconf 열은 graphql 스크립트 재사용으로 이 leaf에서는 전 행 0이며 정보가 없음 — 배선 판정은 애노테이션 전수와 main_other 열로 수행 |
| EVD-080 | suite 검증 | analysis/17-adapter-inbound-websocket.md §26.5 | 2026-08-30 | :adapter:inbound:websocket:test → BUILD SUCCESSFUL, GRADLE_EXIT=0, classes=91 tests=720 failures=0 errors=0 skipped=0; P1(§4.1)은 720개 전부 통과 상태에서 나옴 | 커스텀 레인 4종(websocketNginxTest·websocketBrokerRelayTest·websocketAdvancedTest·websocketJettyTest)은 Docker·별도 서버·외부 브로커를 요구해 실행하지 않음 |
| SRC-156 | module map / denominator | evidence/raw/227-app-bootstrap-module-inventory.txt | same revision | 455 tracked files(main 157 · test 288 · functionalTest 4 · sampleOffTest 1 · conditionalTransportTest 1 · governance 4 · resources 7), main Java 12,380 LOC · test Java 32,568 LOC(main의 2.6배); 조립 표면 전체가 네 리소스 파일 — .imports 6줄 · spring.factories(EnvironmentPostProcessor 6 · SpringBootExceptionReporter · AutoConfigurationImportFilter · ApplicationListener) · ManagementContextConfiguration .imports 1줄 · CaSkeletonApplication의 두 스캔 | 초기 sizing |
| SRC-157 | 활성화 모델과 런타임 멤버십 | evidence/raw/228-app-bootstrap-activation-probes.txt | same revision | 62/62 FULL_READ; shared-contract의 MasterSwitch enum이 다섯 어댑터(jpa·mongo·messaging·notification·graphql)의 프로퍼티·환경변수를 SSOT로 갖고 네 장치를 구동 — 값 문법 거부(MasterSwitchEnvironmentPostProcessor) · 능력 의존 검증(CapabilityDependencyValidator 156) · 액추에이터 보고(AdapterActivationReport, "the application's answer" ) · 삼자 일치 테스트(enum ↔ docs/registries/env-keys.yaml ↔ application.yml, "a sixth adapter cannot be added without this test demanding its row"); modules.json의 runtime_memberships가 grpc=[] · websocket=[] · graphql=["app-bootstrap"] · web=["app-bootstrap","sample-portfolio"] 이고 ConditionalTransportCompositionContractTest가 grpc·websocket을 BUILD_ONLY_TRANSPORTS("nothing may put them on a runtime")로 기계 강제 — 두 어댑터가 활성화 모델 밖인 것은 누락이 아니라 일관성; 남는 것은 출하되는 web의 스위치 넷(backend.web.mvc·webflux 기본 켜짐 포함)이 모델 밖이라는 점 | 이 확인으로 모듈 17 §4.1을 P1 → P2로 하향(모듈 17 §26.6) |
| SRC-158 | 시작 검증기 배선과 조립 규칙 | evidence/raw/230-app-bootstrap-runtime-probes.txt | same revision | 85/85 FULL_READ; runtime 검증기 12종 전부 배선(RuntimeSafetyConfig @Bean 7 · SecretSourceConfig · MigrationStartupConfig), StartupFailures(75)가 구조화 실패 로그의 단일 발생원이며 종료 코드까지 규정(STARTUP_VALIDATION_FAILED=78 · MigrationFailed=70); main 157 파일에 고아 0 — 참조 0인 파일은 전부 @Configuration 루트 · logback 컴포넌트(logback-spring.xml이 클래스명으로 등록) · spring.factories 항목으로 설명됨; 시작 검증기가 도는지 여부가 그 능력에 자동설정 루트가 있는지와 정확히 일치(app-bootstrap 12종·fileserver attest·graphql 검증기는 배선, web·websocket 검증기는 미배선) | — |
| SRC-159 | 아키텍처 규칙 · 계약 레인 | evidence/raw/233·234·235-app-bootstrap-*-probes.txt | same revision | 172/172 FULL_READ(90+54+28); 아키텍처 규칙 14종이 프로덕션 트리에 적용되고 위반/허용 합성 픽스처 76개가 각 규칙의 양방향을 고정; 계약 테스트 30종이 레지스트리 일치·관측/로그·보안 표면·활성화·실패 분류·운영을 덮고 ContractSuiteCompletenessTest가 스위트 자체의 완전성을 검사; dev.caskeleton.onboarding.** 14파일이 "새 feature 추가 절차"의 합성 대상; 대체 소스셋 3종(functionalTest 4 · sampleOffTest 1 · conditionalTransportTest 1) | — |
| EVD-081 | suite 검증 | analysis/18-app-bootstrap.md §26 | 2026-08-30 | :app-bootstrap:test → GRADLE_EXIT=1, classes=169 tests=1016 failures=1 errors=0 skipped=4; 유일한 실패 ComposeMergeCharacterizationTest.everyLaneMatchesItsContract는 환경 원인(분석 컨테이너에 jq 없음 → verify-compose-profile-contracts.sh exit 78); 같은 테스트가 docker compose 부재는 Assumptions.assumeTrue로 skip하고 jq 부재는 실패로 처리하는 가드 비대칭을 P3로 기록 | 나머지 1,015개 통과 |
| SRC-160 | family map / denominator | evidence/raw/251-messaging-leaf-registry-and-memberships.txt · 243-messaging-core-contracts-inventory.txt | same revision | modules.json에서 gradle_path가 :messaging:인 leaf 25개 전량 열거 + 각 source_path에 git ls-files — leaf 합계 549, src/messaging 전체 550(차이는 가족 공통 CLAUDE.md 1개), 미배정 0; 출하 18 / build-only 7(testkit · pulsar · nats · scs-bridge · schema-avro · kafka-share · schema-protobuf); 등록 id 주의 — messaging-inbox-jdbc-postgresql / messaging-outbox-jdbc-postgresql / messaging-cloudevents(schema 접두사 없음), 디스크의 -inbox-jpa·-outbox-jpa는 추적 파일 0으로 분모 밖 | 이 18/7 구분이 문서 전체의 심각도 축(모듈 17 §26.6 원칙 적용) |
| SRC-161 | 공개된 주장의 검증 | evidence/raw/244-messaging-fault-scenarios-vs-evidence.txt · 246-messaging-mss022-no-string-matching.txt · 250-messaging-certification-gate-chain.txt | same revision | src/messaging/CLAUDE.md의 Stable 승격 조건 중 코드로 검증 가능한 3개 전부 성립; MSG-022(예외 타입 문자열 판별) 25 leaf main 전체 0건; NetworkFaultScenario 5개 중 Kafka 증거 4개이고 미커버 connection-refused는 CertifiedEvidence.knownGaps가 all() - covered로 파생하며 aScenarioWithNoLineInTheManifestIsAGapRatherThanAnAbsence가 이유까지 단언; verifyMessagingCertificationEvidence가 실행 산출물 ↔ 커밋 manifest를 양방향 대조(gitCommit·observedAt은 정규식 제거 후 비교, upToDateWhen{false}, CI가 src/messaging/** PR마다 실행) — manifest의 gitCommit: e98b56eb03ec가 분석 리비전보다 오래된 것은 설계상 정상 | 19개 모듈 중 공개 주장이 검증을 그대로 통과한 첫 사례 |
| SRC-162 | capability 집행 · profile validator 도달성 | evidence/raw/247-messaging-capability-flag-enforcement-census.txt · 248-messaging-profile-validator-reachability.txt · 249-messaging-startup-profile-validation.txt | same revision | MessagingCapabilities 12개 플래그의 main/test 참조 전수 — main이 읽는 것 3개(orderedStream·delayedDelivery는 분기, deduplicatedPublish만 거부), 나머지 9개는 모든 어댑터가 선언하고 아무 곳도 읽지 않음(census의 orderedStream main=5 중 4건은 Spring ObjectProvider.orderedStream() 오탐); javadoc의 "fails loudly — at startup where possible"가 성립하지 않음; profile validator 8개 중 조립 3개(DestinationProfileValidator·KafkaProfileValidator·RabbitProfileValidator) — 미조립 5개 중 4개는 build-only leaf라 등급 일치이고 출하 leaf의 KafkaTransactionProfileValidator만 결함(@Bean 선언만, 주입처 없음); StartupProfileValidation javadoc이 같은 결함을 이미 한 번 고친 이력을 서술 | PulsarProfileValidator는 테스트조차 0건 |
| SRC-163 | schema · 관측 도달성 | evidence/raw/252-messaging-schema-and-observability-reachability.txt · 253-messaging-observation-assembly.txt · 254-messaging-autoconfiguration-imports.txt | same revision | 출하 leaf의 main 참조 0 타입 — SchemaCompatibilityValidator(+SchemaRegistry main 구현 없음, DestinationSettings가 NONE_EXPERIMENTAL 설정을 허용), DefaultCloudEventMapper(출하 leaf이자 starter implementation 의존인데 소비자 0), MessagingMetrics·MessagingTracer·MessagingAuditSink·DefaultMessagingObservationConvention; MessagingCoreAutoConfiguration이 관측 관련으로 등록하는 것은 MessagingRedactor·CardinalityGuard 협력자 둘뿐이고 messagingPublisher가 6인자 생성자를 골라 NO_OBSERVATION을 주입 — DefaultMessagePublisher 필드 javadoc의 "an unobserved publish path is how 'the dashboards were empty during the incident' happens"가 조립에서 되돌려짐; AutoConfiguration.imports는 MessagingPlatformRootAutoConfiguration 1줄 | 자동설정 클래스 28개, 그중 .imports에 오르는 것은 루트 하나 |
| SRC-164 | 문서 ↔ 코드 capability 전수 대조 | evidence/raw/255-messaging-capability-doc-vs-code-drift.txt | same revision | docs/messaging/support-matrix.md capability 표 60칸(5 어댑터 × 12 플래그)을 각 어댑터의 MessagingCapabilities 배열과 전수 대조 — 불일치 1칸: Kafka deduplicatedPublish가 문서 O, 코드 false; 그 플래그가 12개 중 유일하게 거부를 발생시키는 것이고, KafkaMessagingTransport의 javadoc이 true→false 변경 이력과 "the caller believes the broker is deduplicating and skips the idempotency it would otherwise build"라는 피해를 서술; Rabbit·Kafka Share·Pulsar·NATS 48칸 전부 일치(Pulsar keyedOrdering은 SHARED/KEY_SHARED 두 배열 차이까지 문서가 반영); Rabbit delayedDelivery는 코드 true / 문서 retry queue로 대행으로 문서가 더 정확 | 이 문서 유일의 P1 |
| SRC-165 | 전송 선택 · Rabbit 조립 · MSG-015 | evidence/raw/256-messaging-provider-selection-and-rabbit-transport.txt · 257-messaging-msg015-two-kafka-stacks.txt | same revision | MessagingPlatformRootAutoConfiguration이 app.messaging.enabled=true를 matchIfMissing 없이 단독 소유하고 자식은 조건을 갖지 않음 — 모듈 14 §8.1이 web에서 없다고 판정한 구조를 messaging은 보유; MessagingProviderSelection.BROKERS_WITHOUT_A_TRANSPORT에 rabbit 등록(RabbitChannelPublisher 구현 0건, RabbitMessagingAutoConfiguration에 MessagingTransport bean 없음) — 코드는 fail-closed로 정직하나 support-matrix.md의 RabbitMQ 행 "제한" 칸이 이를 말하지 않음; MSG-015는 bean 이름 분리로 증상만 사라짐 — KafkaSenderConfig는 app.messaging.broker=kafka만 보고 enabled를 보지 않아 CLAUDE.md가 말한 기본값 보호(enabled=false)가 두 스택 중 하나만 막음 | 오늘 실제 배포 가능한 브로커는 Kafka 하나 |
| SRC-166 | reliability · admin 도달성 | evidence/raw/258-messaging-reliability-and-admin-reachability.txt · 260-messaging-admin-plane-assembly.txt | same revision | MessagingReliabilityAutoConfiguration의 조건 사슬 뿌리가 OutboxRepository/InboxRepository bean인데 유일 구현 JdbcOutboxRepository·JdbcInboxRepository의 main 참조가 0 — relay·worker·lifecycle·cleanup·transactional inbox handler 전부 미조립(19 main 파일 2,818 LOC); MessageCodecRegistry에는 @ConditionalOnMissingBean 기본 구현을 제공한 같은 starter가 여기서는 만족되지 않는 @ConditionalOnBean을 남김; claim-check 배선 0; admin plane은 app.messaging.admin.enabled=true fail-closed에 DestructiveOperationGuard(false)·비내구 journal + MessagingAdminDurabilityValidator(production 프로파일 거부, 공급할 클래스 이름을 메시지에 포함)로 가드는 우수하나 DefaultMessagingAdminService·HmacApprovalVerifier·TopologyValidationRuntime main 참조 0 — 부재 4건 중 DestructiveMessagingAdmin 하나만 javadoc으로 설명됨 | admin 게이트는 이 저장소에서 가장 잘 조립된 축에 속함 |
| SRC-167 | Flyway 마이그레이션 네임스페이스 | evidence/raw/259-messaging-flyway-migration-namespace.txt | same revision | 합성 루트의 기본 Flyway 위치는 PostgreSqlPersistenceConfig:115의 classpath:db/migration/postgresql이고 조건부 스트림은 각자 위치·history table 보유; db/migration/messaging을 이름으로 부르는 main 코드가 저장소 전체에 0건 — messaging_outbox·messaging_inbox·admin journal 테이블은 어떤 출하 배포에서도 생성되지 않음; 두 leaf가 같은 리소스 디렉터리에 각자 번호를 매겨 V2가 둘(V2__messaging_inbox.sql CREATE TABLE vs V2__messaging_outbox_lease_fencing.sql ALTER×4) — 그 위치를 Flyway에 주는 순간 duplicate version으로 부팅 실패; 각 leaf의 IT는 자기 jar 리소스만 보므로 재현 불가; 원래 구현 계획서(plan:3010·3011·3032·3055)는 messaging-outbox/messaging-inbox 분리 위치를 지정했음 | persistence-jpa가 세 번 고친 "bean은 있고 테이블은 없다"의 정반대 형태 |
| SRC-168 | 문서 계약 테스트 커버리지 · 설정 위생 | evidence/raw/261-messaging-documentation-contract-test-coverage.txt · 262-messaging-starter-configuration-validators.txt | same revision | MessagingDocumentationContractTest가 doc rot를 막기 위해 존재하고("the only signal is an operator making a decision on a page that stopped being true months ago") 단언 8개를 가짐 — 등급 이름·Kafka 버전·존재하지 않는 두 상수는 정확히 붙들고, capability 표·runtime membership 문장·브로커 등급표의 "제한" 칸은 커버리지 밖이며 이 문서가 찾은 문서 드리프트 3건이 전부 그 밖에 위치; 약한 단언 둘(theExperimentalPolicyStatesThatExperimentalIsOffByDefault = contains("false"), everyDocumentHasContent = 500자 초과); starter는 시작 검증기 6종을 실제로 실행 — MessagingPrefixMigrationValidator(죽은 세 네임스페이스) · MessagingConfigurationKeyValidator(적법 키를 settings record에서 파생) · MessagingCredentialRequirementValidator(production 한정) · MessagingAdminDurabilityValidator · Kafka/Rabbit StartupProfileValidation 2종 | MessagingPublicSurfaceContractTest는 src/messaging 밖(app-bootstrap) 레인에 있음 |
| EVD-082 | suite 검증 | analysis/19-messaging-platform.md §12.1 | 2026-08-31 | 25개 messaging leaf의 :test 전량 → BUILD SUCCESSFUL in 2m 27s, GRADLE_EXIT=0, 105 actionable tasks(59 executed · 46 up-to-date); XML 집계 classes=110 tests=851 failures=0 errors=0 skipped=0; git status --short 출력 없음 | messagingCertificationTest/verifyMessagingCertificationEvidence(Docker 필수, 의도적으로 가드 없음)와 Testcontainers 계열 IT는 실행하지 않음 |
| SRC-169 | 리비전 이동 · 분모 재확정 | evidence/raw/264-cross-scope-autoconfiguration-roots.txt(이동 전) · 265·268(이동 후) | 21234e38 | 교차 스코프 준비 중 레지스트리 전수 재독으로 등록 62 / state.json 44 불일치 발견. 원인은 분석 누락이 아니라 리비전 이동 — 기준선 a24ece9c 이후 21234e38("feat: grpc 기능 deep 구현", 2026-08-31)이 gRPC 가족을 추가했다. git diff a24ece9c..HEAD = 400 files / +40,217 / −4이고 변경 경로는 src/grpc* · modules.json(18항목 추가) · src/build.gradle(테스트 클래스패스 조건) · docs 15개뿐 — src/messaging 이하 무변경, 모듈 01~19 전부 유효; state.json의 gitRevision을 HEAD로 올리고 reanalysis를 ADDITIVE_SCOPE로 채운 뒤 18 스코프 추가 | evidence 264는 이동 전 트리(.imports 7 · leaf 44), 265·268은 이동 후(.imports 8 · leaf 62) |
| SRC-170 | grpc family map / denominator | evidence/raw/266-grpc-family-claims-verification.txt | same revision | 18 leaf · 추적 383(leaf 381 + 가족 CLAUDE.md 2) · main Java 260 / 18,726 LOC · test Java 74; 18개 전부 runtime_memberships: [] — 가족 전체 build-only이고 이것이 심각도 축(모듈 17 §26.6 원칙); adapter-inbound-grpc의 allowed_dependencies가 [domain-core, application-core, shared-contract]로 이 가족을 볼 수 없음 — messaging MSG-015 재발 방지가 레지스트리로 성립 | 6개 sub-scope, 미배정 0 |
| SRC-171 | 공개 주장 검증 (6건 성립) | evidence/raw/266-grpc-family-claims-verification.txt | same revision | grpc-core-api의 io.grpc 참조 3건은 전부 javadoc 산문이고 build.gradle의 dependencies {}가 비어 있어 framework-free가 클래스패스로 강제됨(32 main / 1,897 LOC); Stable→advanced 금지가 레지스트리 0위반 · 소스 0참조 · verifyCleanArchitectureDependencies · GrpcStableBuildInvariant 네 층 일치; GrpcEvidenceGrade.requireCertifies가 CONTRACT 등급의 tls 주장을 런타임 거부(등급 집합을 필드가 아니라 switch로 계산); 성능 레인 excludeTags 'grpc-performance'; 지원 매트릭스가 "Not released … build-only"와 미해결 게이트 입력 2건을 스스로 공시 — 모듈 19 §6.4(messaging 매트릭스의 반대 주장)와 정반대 사례; GrpcCompatibilityMatrix.caSkeleton() 7레인이 문서 표와 전수 일치 | Spring Boot 4.0.8 · UDS resolver 존재도 문서와 일치 |
| SRC-172 | 조립·릴리스 게이트 도달성 | evidence/raw/267-grpc-family-reachability.txt · 268-grpc-assembly-and-release-gate.txt | same revision | 유일한 조립 지점 GrpcPlatformAutoConfiguration(.imports 1줄, matchIfMissing=false fail-closed)이 @Bean 9개를 등록하는데 전부 프로파일·정책이고 서버·인터셉터 체인·서비스 어댑터가 없음; GrpcPlatformStartupValidator main 참조 0(static 메서드, 호출자 없음)인데 CLAUDE.md는 "startup을 거부한다"고 현재 시제 서술 — 모듈 14 §44.2·17 §4.1·19 §3.5에 이은 네 번째이자 자동설정 루트가 있는데도 부르지 않는 첫 사례; GrpcReleaseEvidence 생성 지점 4개가 전부 GrpcStableReleaseGateTest이고 runbookPresent 등 5성분이 호출자 제공 boolean — messaging이 manifest 파일 + Gradle 태스크 + CI 워크플로 3층으로 이미 닫은 모양의 재발; src/grpc*/*/build.gradle의 tasks.register 0건, 28개 CI 워크플로 중 grpc 언급 0건; main 260 중 참조 0이 73개(공개 API 표면 포함)이고 그중 조립·기계 타입 15종이 결함 | GrpcServerInterceptorChain javadoc이 "every codebase gets it backwards at least once"라 적고 조립에서 안 쓰임 |
| SRC-173 | 증거 레인의 실행 경로 | evidence/raw/268-grpc-assembly-and-release-gate.txt | same revision | ca.strict-test-lane.gradle이 레인을 verification 그룹 Test 태스크로 등록만 하고 check에 연결하지 않음(check-dependsOn 0건); CI는 ci-quality-gates.yml:50의 ./gradlew check로 각 leaf 기본 test만 커버; 따라서 CONTRACT/TRANSPORT/FAULT 등급을 뒷받침하는 25개 테스트(7+9+9)가 누군가 명령을 직접 입력할 때만 실행됨 — 직접 실행해 전부 통과 확인(BUILD SUCCESSFUL, exit 0); 모듈 18 §4.1c의 "a gate that is red in a lane nobody runs locally…"가 그대로 적용되되 이쪽은 오늘 초록 | messaging은 같은 제외에 전용 CI 워크플로라는 대체 경로가 있음 |
| EVD-083 | suite 검증 | analysis/20-grpc-platform.md §6.1 | 2026-08-31 | 18개 grpc leaf :test 전량 → BUILD SUCCESSFUL in 1m 12s, GRADLE_EXIT=0, 81 actionable tasks; XML 집계 classes=71 tests=579 failures=0 errors=0 skipped=0; 증거 레인 3종 직접 실행 → BUILD SUCCESSFUL, exit 0 (inProcess 7 · netty 9 · fault 9, 전부 0 실패 0 skip, Netty는 실제 소켓); git status --short 출력 없음 | grpcPerformanceTest는 공유 러너 측정이 baseline이 될 수 없어 미실행 |