docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
43bccd08a8
commit
b2963105a8
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-cloudevents-f03
|
||||
title: 왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-cloudevents-f03
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-cloudevents.md#L538
|
||||
---
|
||||
|
||||
# 왕복이라 부르는 테스트는 무엇을 보존하지 않는지도 적는다
|
||||
|
||||
## 관계
|
||||
|
||||
- **배포 아티팩트가 싣지만 아무도 부르지 않는다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **상호운용을 위한 매퍼가 명세 준수 이벤트를 분류되지 않은 예외로 거절한다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
이름이 왕복이라고 말하는 테스트가 실제로는 부분 보존만 확인할 때, 읽는 사람은 확인되지 않은 필드를 확인된 것으로 읽는다. 그 착각이 가장 비싸게 끝나는 필드가 trace 다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 비교하는 필드와 왕복하는 필드를 각각 센다
|
||||
fromCloudEvent 가 partitionKey 와 orderingKey 를 empty 로, traceContext 를 none() 으로, headers 를 empty() 로 두고 producedAt 을 occurredAt 값으로 덮는다. 테스트는 여섯 필드만 비교하고 이 다섯을 비교하지 않는다.
|
||||
|
||||
2. 비교하지 않는 필드가 실제로 어긋나는지 확인한다
|
||||
fixture 의 producedAt 은 09:15:01Z, occurredAt 은 09:15:00Z 다. 비교했다면 실패했을 값이다.
|
||||
|
||||
3. 소실을 계약에 적거나 테스트 이름을 실제 보장에 맞춘다
|
||||
messaging-core-api 의 TraceContext javadoc 이 그 필드를 봉투에 둔 이유를 "a trace survives an Outbox round trip through the database, where broker headers do not exist yet" 라고 적는다. CloudEvents 왕복이 그 보존을 깨뜨리면서, CloudEvents 자신이 정의하는 distributed-tracing extension 도 쓰지 않는다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
매핑이 양방향이고 한쪽 방향에서 필드가 줄어드는 모든 코덱·어댑터 경계.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 의도적으로 버리는 필드가 있다면 그 목록이 javadoc 에 있어야 한다는 것이 여기서 제시된 후보 중 하나다.
|
||||
|
||||
## 예시
|
||||
|
||||
DefaultCloudEventMapper.java:115-131 의 매핑과 CloudEventMappingTest.java:72-84, 143-161 의 비교 대상.
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-kafka-share-experimental-f05
|
||||
title: leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-kafka-share-experimental-f05
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-kafka-share-experimental.md#L503
|
||||
---
|
||||
|
||||
# leaf의 각 public 클래스는 자기 레인에 테스트를 갖는다
|
||||
|
||||
## 관계
|
||||
|
||||
- **"등록"이 아무것도 등록하지 않고 성공을 반환한다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
네 타입 중 KafkaShareProfileValidator 만 테스트를 갖는다. registrar 에 테스트가 있었다면 register 가 spec 을 버리는 것이 sink 호출 확인에서 바로 드러났을 것이고, capability 의 boolean 12개는 지금 순서 값을 true 로 바꿔도 아무것도 깨지지 않는다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 테스트 클래스 이름 목록과 public 타입 목록을 맞춘다
|
||||
find src/test -name '*Test.java' 가 하나를 돌려준다.
|
||||
|
||||
2. 짝이 없는 타입이 무엇을 혼자 결정하는지 센다
|
||||
registrar 는 register 의 spec 처리를, capability 는 12개 boolean 선언을 혼자 갖는다.
|
||||
|
||||
3. 선언만 있는 상수도 테스트 대상이다
|
||||
읽는 코드가 없더라도 값이 바뀌면 안 되는 것이면 그 사실을 테스트가 붙든다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
타입 수가 적어 테스트 하나로 충분해 보이는 leaf. 특히 미배선 상태라 실행 경로가 없는 leaf.
|
||||
|
||||
## 예외
|
||||
|
||||
테스트가 소비자 leaf 에 있는 경우는 예외로 볼 수 있다. 이 leaf 는 소비자가 0 이라 그 예외에 해당하지 않는다.
|
||||
|
||||
## 예시
|
||||
|
||||
테스트 클래스 목록이 하나라는 것과, 그 하나가 validator 를 겨냥한다는 것.
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-reliability-api-f04
|
||||
title: 계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-reliability-api-f04
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-reliability-api.md#L716
|
||||
---
|
||||
|
||||
# 계약만 담는 leaf도 계약의 거절 조건은 자기 레인에서 검증한다
|
||||
|
||||
## 관계
|
||||
|
||||
- **inbox 보존 규칙이 문서로만 있다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 `@Deprecated`가 없다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
계약 불변식 중 일부는 구현이 우연히 그 조합을 만들지 않으면 한 번도 실행되지 않는다. OutboxCanonicalMetadata 가 schemaUri 있고 schemaSubject 없는 조합을 거절하는 것, OutboxLease 가 token < 1 을 거절하는 것, InboxResult.isSafeToSettle 의 세 값이 그런 것들이다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. leaf 에 src/test 가 있는지부터 본다
|
||||
messaging-reliability-api 에는 그 디렉터리가 없다. 13개 타입의 record 생성자 검증 여섯과 술어 셋이 이 leaf 의 레인에서 실행되지 않는다.
|
||||
|
||||
2. 형제 leaf 의 기준선을 확인한다
|
||||
messaging-core-api 79개, messaging-policy 42개다. 계약 leaf 라서 테스트가 없는 것이 아니다.
|
||||
|
||||
3. 거절 조건과 술어를 겨냥한 단위 테스트를 둔다
|
||||
구현이 지나가는 경로가 아니라 계약이 금지하는 조합을 겨냥한다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
타입 선언과 javadoc 만 담는 계약 leaf. 특히 record 생성자가 검증을 갖는 leaf.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 검증이 전혀 없는 순수 인터페이스 leaf 라면 대상이 아니지만, 이 leaf 는 생성자 검증 여섯을 갖는다.
|
||||
|
||||
## 예시
|
||||
|
||||
ls src/messaging/messaging-reliability-api/src 가 main 만 돌려준다는 것. 원문 근거는 evidence/raw/289 §A 이다.
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-reliability-api-f07
|
||||
title: record의 equals를 좁히면 이유를 적는다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-reliability-api-f07
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-reliability-api.md#L743
|
||||
---
|
||||
|
||||
# record의 equals를 좁히면 이유를 적는다
|
||||
|
||||
## 관계
|
||||
|
||||
- **inbox 보존 규칙이 문서로만 있다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **포트가 bounded/unbounded purge 두 오버로드를 나란히 노출하고, 호출자가 무제한 쪽을 고른다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **fencing token 경로가 실제 데이터베이스에 대해 실행되지 않는다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **한 인터페이스가 같은 전이의 두 세대를 갖고, 안전하지 않은 쪽에 `@Deprecated`가 없다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
같은 messageId · status · attempts · payload 를 가진 두 행이 다른 목적지, 다른 provenance 를 가져도 같다고 판정된다. 컬렉션 연산과 테스트 단언에서 의미가 달라지는데, 그 좁힘의 이유가 어디에도 없다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 어떤 필드를 비교에서 뺐는지 센다
|
||||
OutboxRecord.equals 와 hashCode 가 넷만 본다. destination · metadata · createdAt · leaseExpiresAt · lastFailureCode 는 무시한다.
|
||||
|
||||
2. 재정의가 필요했던 이유와 좁힌 이유를 구분한다
|
||||
배열 필드 때문에 재정의가 필요한 것까지는 명확하다. messaging-schema-api 의 EncodedMessage 도 같은 이유로 재정의한다.
|
||||
|
||||
3. 같은 이유에서 출발한 형제와 대조한다
|
||||
EncodedMessage 는 모든 필드를 비교한다. 여기서 갈라진 지점이 기록돼야 할 자리다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
배열 필드나 파생 필드 때문에 record 의 기본 equals 를 재정의하는 모든 자리.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 신원 필드만으로 동등성을 정의하는 설계가 의도라면 그 문장이 javadoc 에 있어야 한다.
|
||||
|
||||
## 예시
|
||||
|
||||
OutboxRecord.java:114-126 의 비교 대상. 확인 방법은 그것과 EncodedMessage 의 equals 를 대조하는 것이다.
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-runtime-core-f06
|
||||
title: 증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-runtime-core-f06
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-runtime-core.md#L754
|
||||
---
|
||||
|
||||
# 증가한다고 문서화한 값이 리터럴이면 그 사실을 적는다
|
||||
|
||||
## 관계
|
||||
|
||||
- **관측이 구현·호출부·주입 자리를 모두 갖추고도 출하에서 no-op이다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **소비 오케스트레이터가 조립되지 않는다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **선언된 content type과 실제 인코딩이 조용히 갈라질 수 있다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
진단에서 generation 을 읽는 사람은 언제나 1 을 본다. 회전 코드가 없는 지금은 무해하지만, DefaultMessagingRuntimeRegistry 의 세대 드레인 로직은 세대 구분을 전제한다. 회전을 붙일 때 이 리터럴이 잊히면 두 세대가 같은 번호를 갖는다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 증가한다고 적힌 값의 설치 지점을 찾는다
|
||||
유일한 지점인 MessagingCoreAutoConfiguration:476 이 리터럴 1L 을 넘긴다.
|
||||
|
||||
2. 문서가 무엇을 약속하는지 확인한다
|
||||
MessagingRuntime.generation() javadoc 은 "increasing with each replacement", TransportMessagingRuntime javadoc 은 "the credential generation a rotation increments" 라고 적는다.
|
||||
|
||||
3. 값을 실제 카운터에 연결하거나 리터럴임을 주석으로 남긴다
|
||||
둘 중 하나가 없으면 문서와 값이 조용히 갈라진 상태로 남는다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
javadoc 이 값의 변화를 약속하고 그 값의 생성 지점이 조립 코드에 하나뿐인 자리.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 값이 영원히 고정이라면 그것이 문서의 표현이어야 하고, 지금은 문서 쪽이 증가를 말한다.
|
||||
|
||||
## 예시
|
||||
|
||||
MessagingCoreAutoConfiguration:476 의 리터럴과 두 javadoc. 확인 방법은 git grep -n 'TransportMessagingRuntime(' -- src/main 이다.
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-schema-avro-f04
|
||||
title: 모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-schema-avro-f04
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-schema-avro.md#L551
|
||||
---
|
||||
|
||||
# 모드 enum을 분기 조건으로 쓰면 각 분기에 테스트를 둔다
|
||||
|
||||
## 관계
|
||||
|
||||
- **진화 판단이 두 곳에 있고 형태가 반대다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **CI에서 돈다고 선언한 게이트를 부르는 CI가 없다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
transitive 모드는 "여러 릴리스 뒤처진 consumer" 를 위한 것이고 그것이 이 게이트가 존재하는 이유의 절반이다. 그 절반이 한 번도 실행되지 않는다. 그리고 그 분기가 §12.3 의 중복 구현이 갈라질 지점이기도 하다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 분기 조건이 되는 enum 값과 테스트가 넘긴 값을 맞춰 본다
|
||||
AvroCompatibilityTest 의 게이트 호출 2건이 모두 SchemaCompatibility.BACKWARD 다. isTransitive 가 true 인 경로가 실행되지 않는다.
|
||||
|
||||
2. 실행되지 않는 분기가 무엇을 결정하는지 센다
|
||||
여기서는 비교 대상 스키마의 개수와 범위가 통째로 달라진다.
|
||||
|
||||
3. 분기마다 입력을 만든다
|
||||
v1 · v2 · v3 세 스키마로 BACKWARD_TRANSITIVE 케이스를 추가한다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
enum 이 알고리즘을 가르는 모든 게이트·검증기·전략 선택 지점.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 분기가 같은 코드로 수렴하는 것이 증명돼 있다면 대상이 아니지만, 여기서는 두 분기가 다른 비교를 수행한다.
|
||||
|
||||
## 예시
|
||||
|
||||
AvroCompatibilityTest.java:134-150 의 모드 인자 두 개. 확인 방법은 두 테스트의 인자를 보는 것이다.
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-schema-protobuf-f01
|
||||
title: 검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-schema-protobuf-f01
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-schema-protobuf.md#L527
|
||||
---
|
||||
|
||||
# 검증되지 않는 스키마 파일은 문서임을 파일 안에 적는다
|
||||
|
||||
## 관계
|
||||
|
||||
- **registry 조회 로직이 세 codec에 복제돼 있다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
테스트 javadoc 이 .proto 를 "the fixture documents" 라고 부르므로 읽는 사람은 그 파일이 테스트의 근거라고 믿는다. 실제로는 테스트가 그 파일을 읽지 않고 DescriptorProto 로 같은 스키마를 손수 만든다. 한쪽만 수정되면 조용히 갈라진다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 스키마 파일이 빌드나 테스트에 입력으로 들어가는지 확인한다
|
||||
src/test/proto/order_created_v1.proto 는 어디에도 입력되지 않는다. 오늘 두 정의는 일치한다 — 필드 4개, 태그 1–4, 타입까지 전수 대조했다.
|
||||
|
||||
2. 검증되지 않는다면 그 사실을 파일 안에 적는다
|
||||
"이 파일은 문서이며 테스트는 descriptor 를 손수 만든다" 가 그 문장이다.
|
||||
|
||||
3. 자동 대조가 가능한지 먼저 따져 본다
|
||||
protoc 없이 protobuf-java 파서만으로는 .proto 를 읽어 descriptor 를 만들 수 없다. protoc 를 뺀 것은 이유가 적힌 설계 결정이다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
빌드 입력이 아닌 스키마·설정 예제 파일이 저장소에 남아 있는 자리.
|
||||
|
||||
## 예외
|
||||
|
||||
빌드가 그 파일을 실제로 소비하면 이 규칙의 대상이 아니다. 여기서는 소비 지점이 없다.
|
||||
|
||||
## 예시
|
||||
|
||||
.proto 전문과 ProtobufCompatibilityTest.java:41-66 의 손수 만든 descriptor. 확인 방법은 두 정의의 필드·태그·타입 대조와 find src/messaging/messaging-schema-protobuf -name '*.proto' 다.
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-schema-protobuf-f02
|
||||
title: 신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-schema-protobuf-f02
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-schema-protobuf.md#L536
|
||||
---
|
||||
|
||||
# 신뢰할 수 없는 입력 쪽 경계를 먼저 테스트한다
|
||||
|
||||
## 관계
|
||||
|
||||
- **registry 조회 로직이 세 codec에 복제돼 있다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
디코딩은 브로커에서 온 바이트를 받는 쪽이다. 지금은 자기 코드가 만든 바이트에 대한 방어가 남이 만든 바이트에 대한 방어보다 잘 검증돼 있다. 형제 leaf 는 반대로 되어 있다 — AvroRegistryBoundsTest.theEvolutionDecodeAppliesTheSameBound 가 정확히 이 각도를 덮는다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 상한 검사가 인코딩 쪽과 디코딩 쪽에 각각 있는지 본다
|
||||
ProtobufMessageCodec.java:104-108 의 if (encoded.length > maxBytes) 가 디코딩 쪽 검사다.
|
||||
|
||||
2. 각 검사에 테스트가 붙었는지 센다
|
||||
인코딩 상한은 두 테스트가 덮고, 디코딩 분기를 겨냥한 테스트는 ProtobufCompatibilityTest 12개 중 없다.
|
||||
|
||||
3. 입력의 출처로 우선순위를 정한다
|
||||
maxBytes 보다 큰 byte[] 로 decode 를 부르는 테스트를 먼저 추가한다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
같은 상한이 인코딩과 디코딩 양쪽에 걸려 있고 한쪽 입력만 외부에서 오는 모든 codec.
|
||||
|
||||
## 예외
|
||||
|
||||
디코딩 입력이 같은 프로세스에서 만들어진다고 타입이 보장하면 대상이 아니다. 이 codec 의 디코딩 입력은 브로커에서 온다.
|
||||
|
||||
## 예시
|
||||
|
||||
ProtobufMessageCodec.java:104-108 의 분기와 ProtobufCompatibilityTest 12개 전수. 확인 방법은 그 12개 중 decode 에 큰 입력을 주는 것이 없음을 보는 것이다.
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
---
|
||||
kind: REFERENCE
|
||||
slug: messaging-security-f05
|
||||
title: 같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다
|
||||
topic: verification-path-coverage
|
||||
project: clean-architecture-backend-template
|
||||
status: 게시 전
|
||||
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
||||
rootTreeNode: reference:messaging-security-f05
|
||||
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
|
||||
source:
|
||||
- analysis/messaging/messaging-security.md#L670
|
||||
---
|
||||
|
||||
# 같은 술어가 두 타입에 있으면 하나가 다른 하나를 부른다
|
||||
|
||||
## 관계
|
||||
|
||||
- **종료 시 자격증명 소거가 호출되지 않는다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **같은 TLS posture를 두 클래스가 다른 엄격도로 검사한다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
- **권한 거부가 `AUTHORIZATION`이 아니라 `CONFIGURATION`으로 기록된다**
|
||||
이 규칙의 근거는 같은 분석 리프의 판정이 소유한다.
|
||||
|
||||
## 목적
|
||||
|
||||
테스트가 고정하는 것과 실행되는 것이 다른 객체다. 한쪽만 고치면 다른 쪽은 조용히 다른 시점에 회전한다.
|
||||
|
||||
## 규칙
|
||||
|
||||
1. 같은 판단을 하는 메서드가 둘인지 센다
|
||||
CredentialRotationPlan.isDue 와 isExpired, CredentialRuntime.isDueForRotation 과 isExpired 가 글자까지 같다.
|
||||
|
||||
2. 실행되는 쪽과 테스트되는 쪽이 같은지 본다
|
||||
전자는 소비자가 0 이고 전용 테스트 CredentialRotationContractTest 4개를 갖는다. 후자가 실행되는 쪽이다.
|
||||
|
||||
3. 위임으로 하나를 만든다
|
||||
CredentialRuntime 이 CredentialRotationPlan 을 필드로 갖고 위임하거나, 계획 record 를 제거한다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
같은 시간·상태 판단이 값 객체와 런타임 객체에 각각 구현되는 자리.
|
||||
|
||||
## 예외
|
||||
|
||||
SSOT 가 이 규칙의 반례를 적지 않았다. 두 술어가 의도적으로 다른 기준을 갖는다면 그 차이가 이름이나 javadoc 에 있어야 하는데, 지금은 본문이 같다.
|
||||
|
||||
## 예시
|
||||
|
||||
두 메서드의 본문. 원문 근거는 evidence/raw/287 §E 이고, 확인 방법은 두 본문을 대조하는 것이다.
|
||||
|
||||
Reference in New Issue
Block a user