Files
document-haness/reviews/2026-09-20-keycloak-session-store-post-remediation-verification.md
T

603 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# keycloak-session-store 후속 검증 리뷰
- 검토일: 2026-09-20
- 대상: 이전 리뷰 `reviews/2026-09-20-keycloak-session-store-seven-stage-review.md` 반영 결과
- 판정: **아직 더 봐야댐**
---
## 1. 결론
이전 리뷰의 **문서 내용 자체는 대부분 제대로 반영됐다.**
특히 다음은 확실히 닫혔다.
- command analyzer가 `bash label="..."`, `sh label="..."`을 읽도록 수정됨
- TechLog Record의 shell block **992개 / 33 Record**를 analyzer가 실제로 인식함
- label의 `[lab host]`, `[워크스테이션]`, `[탐침 파드]` 같은 실행 위치를 execution context로 인식함
- 관련 회귀 테스트가 추가됨
- Tree의 미처분 SSOT 절이 `KEEP_IN_SSOT / CONFIRMED`로 처분됨
- `이 기준이 선 근거.``이 기준의 근거다.`로 수정됨
- prose/voice는 현재도 **61/61 PASS**
- TechViz가 직접 근거로 삼는 `current_section`**31/31 최신 SSOT와 일치**
- Figure Text / Overlap / Provenance 모두 PASS
- 전체 pipeline은 exit 0
- 전체 unittest는 **397 PASS / 14 skipped**
따라서 이전처럼 “문서 내용이 많이 남아 있다”는 상태는 아니다.
하지만 **완료를 증명하는 현재 remediation run의 관문 기록이 하네스 계약과 맞지 않는다.**
이 문제가 남아 있어서 현재 상태를 `완료`로 판정하면 안 된다.
---
# 2. 이전 리뷰 항목별 재검증
## 2.1 Command analyzer — 반영됨
이전 문제:
> analyzer가 `bash label=...`, `sh label=...`을 읽지 못해 shell block 99.2%를 놓쳤다.
현재 `scripts/command_pedagogy.py`는 fence의 첫 info token을 언어로 읽는다.
현재 전수 결과:
```text
Record 61
command-bearing Record 33
shell block 992
```
즉 이전에 빠졌던 labeled fence까지 모두 잡힌다.
현재 테스트에도 다음 계약이 들어갔다.
- labeled bash fence 분석
- labeled sh fence 분석
- 첫 token 전체 일치 검사
- label execution context 인식
- context가 아닌 label은 remote execution context를 숨기지 못함
이 항목은 **반영 완료**로 본다.
---
## 2.2 Command corpus 재분석 — 내용상 큰 결함은 새로 나오지 않음
기존 corpus 정책대로 `reference` mode로 61 Record 전체를 다시 분석했다.
```text
command-bearing Record = 33
shell blocks = 992
findings = 53
major findings = 0
command-like text = 15
```
남은 53개 deterministic signal:
```text
hidden-stderr 48
compound-remote-shell 5
```
이것들은 전역 금지 항목이 아니다.
실제 문맥을 다시 확인하면 대표적으로:
- OpenSSL의 handshake noise를 없앤 뒤 x509 값을 보는 경우
- JWT payload를 base64 decode하면서 decode stderr를 숨기는 경우
- build/restore 출력을 `/tmp/*.log`로 모은 뒤 그 파일을 읽는 경우
- `nginx -t && nginx -s reload`처럼 **검증 성공 뒤에만 변경**하는 안전 조건
- conntrack 실험처럼 stderr 억제가 어떤 오판을 만드는지 본문이 오히려 설명하는 경우
가 대부분이다.
따라서 현재 전수 재검사에서 **새로운 high-confidence command defect는 발견하지 못했다.**
다만 아래 §4의 **검토 증거 범위 문제**는 별개다.
---
## 2.3 Tree 미처분 절 — 반영됨
이전 미처분 절:
```text
2026-09-17 재현 — 어디까지 밟았고 무엇이 막았나
```
현재 tree에는 새 candidate가 생겼다.
```text
id: SSOT-2026-09-17-reproduction-progress-and-blocker
disposition: KEEP_IN_SSOT
dispositionReview: CONFIRMED
```
이유도 적절하다.
- 시점 의존적인 진행 추적 정보
- 각 Setup이 실제 절차와 미완료 단계를 이미 담음
- 별도 Record로 올리면 중복
현재 Tree 결과:
```text
records=61
written=61
unwritten=0
KEEP_IN_SSOT=23
warn=1
```
남은 warn 1은 source repository 부재뿐이다.
이 항목은 **반영 완료**다.
---
## 2.4 깨진 문장 — 반영됨
이전:
```text
이 기준이 선 근거.
```
현재:
```text
이 기준의 근거다.
```
또 Relation의 반복 문형도 일부 선별 정리했다.
예:
```text
이 절차가 만드는 두 시각의 차이에 대한 결론은 그 기록에 있다.
```
등으로 바뀌었다.
현재:
```text
check_prose 61/61 PASS
check_voice 61/61 PASS
```
이 항목은 **반영 완료**다.
---
# 3. SVG — 본문 근거는 닫혔지만 layout warning 7개는 남음
이전에는 31개 중 28개가 현재 SSOT section과 달랐다.
현재 직접 비교 결과:
```text
current_section exact match = 31 / 31
```
**그림이 직접 근거로 삼는 현재 절은 전부 최신 SSOT와 맞는다.**
Figure gate도:
```text
Figure Text PASS 31/31
Figure Overlap PASS 31/31
Figure Provenance PASS 31/31
```
이다.
따라서 이전의 “28개 그림이 옛 본문을 보고 있다”는 핵심 문제는 닫혔다.
다만 `verify-project-layout.py`에는 아직 **7개 context warning**이 남는다.
```text
a1-transport-vs-discovery
d2-upgrade-direction
lab-topology
measurement-control
observation-points
open-questions-answered
wrong-predictions
```
세부적으로 보면 앞의 여섯 개는:
- `current_section` = MATCH
- `next_section` = MATCH
- 상위/이전 parent section snapshot만 STALE
인 형태다.
`wrong-predictions`는:
- previous = MATCH
- current = MATCH
- next `자료` section = STALE
이다.
**그림 자체의 직접 근거가 낡았다는 의미는 아니다.**
여러 child section을 포함하는 parent/neighbor context가 뒤의 SSOT 수정 때문에 다시 달라진 잔여 warning이다.
그래도 현재 verifier가 이를 stale context로 보고 있으므로 최종 cleanup은 필요하다.
권장:
1. 모든 SSOT 수정이 끝난 뒤 이 7개 context를 마지막에 다시 prepare
2. spec의 semantic node/edge가 그대로인지 확인
3. semantic 변화가 없으면 context/evidence hash만 최신화
4. render → lint → text → overlap → provenance → preview
5. 다시 `verify-project-layout.py keycloak-session-store`
또는 parent section 전체를 previous context로 잡는 구조가 계속 연쇄 stale을 만든다면 verifier/context 모델을 별도 개선한다.
**SVG 내용 자체는 현재 정상으로 보지만, layout warning 7개는 아직 정리되지 않았다.**
---
# 4. 완료 차단 — 새 remediation run이 evidence gate에서 `--repo`를 빼고 PASS를 만들었다
이것이 현재 가장 중요한 finding이다.
현재 authoritative stage contract의 S3 gate:
```bash
node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs <프로젝트> --repo
```
S5와 S6도 S3 gate를 다시 실행하므로 동일하게 `--repo`가 필요하다.
또 현재 pipeline skill은 명확히 적는다.
```text
exit 0 = 저장소 대조 완료
exit 1 = 실제 불일치
exit 2 = 검사 대상 불성립
exit 3 = source repo 부재로 UNVERIFIABLE
새 publication run에서는 exit 3을 PASS로 기록하면 안 된다.
```
그런데 새로 만든 remediation run 6개를 확인하면 S3/S5/S6가 전부 다음처럼 기록돼 있다.
```bash
node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs keycloak-session-store
```
**`--repo`가 없다.**
대상 run:
```text
2026-09-20-1725-remediation-01-setup-reproduce-d4-certificate-renewal
2026-09-20-1725-remediation-02-setup-reproduce-d4a-deploy-hook
2026-09-20-1725-remediation-03-setup-reproduce-a7a-volatile-cause
2026-09-20-1725-remediation-04-setup-reproduce-b7a-orphan-session
2026-09-20-1725-remediation-05-reference-look-at-the-lookup-key-before-moving-the-store
2026-09-20-1725-remediation-06-setup-reproduce-b6-key-rotation
```
6 run × S3/S5/S6 = **18개 evidence gate 전부 `--repo` 누락**이다.
실제로 현재 머신에서 실행하면:
### 현재 run이 기록한 명령
```text
check_evidence.mjs keycloak-session-store
→ exit 0
→ 문제 없음
```
### 계약에 적힌 명령
```text
check_evidence.mjs keycloak-session-store --repo
→ exit 3
→ 저장소 경로가 이 기계에 없다
→ 불일치 0 / 대조 불가 1
```
즉 현재 run은 **원본 대조를 수행하지 않은 명령을 실행하고 PASS라고 기록했다.**
사용자와 합의한 기준상 source repository 부재 자체는 완료 차단으로 보지 않아도 된다.
하지만 그것은:
> 원본 대조를 하지 않고 PASS로 바꿔도 된다
는 뜻이 아니다.
정확한 상태는:
> **live source reconciliation = UNVERIFIABLE**
이다.
## 필요한 수정
기존 17:25 remediation run은 이미 만들어진 영수증이므로 고쳐 쓰지 않는다.
대신 둘 중 하나로 해결한다.
### A. source repo가 실제로 있으면
정본 경로를 찾아 tree의 sourceRepository를 실제 경로에 맞춘 뒤:
```text
check_evidence --repo
→ exit 0
```
으로 새 verification/remediation run을 만든다.
### B. source repo가 이 환경에는 없고 이를 사용자 예외로 허용한다면
**`--repo`를 삭제하지 말고** 결과를 그대로 남길 수 있어야 한다.
즉 run schema/verifier에 명시적인 상태를 둔다.
예:
```text
status: UNVERIFIABLE
exit: 3
reason: source repository unavailable on current machine
acceptedByProjectReview: true
```
이름은 달라도 된다.
핵심은:
- 실제 명령은 `--repo` 포함
- 실제 exit 3 보존
- PASS로 위장하지 않음
- 이 프로젝트에서는 사용자가 허용한 환경 제약이므로 전체 완료를 막지 않는다는 정책을 별도 표현
이다.
현재처럼 flag 자체를 빼는 방식은 안 된다.
---
# 5. verifier blind spot — 잘못된 gate인데 run verifier가 PASS한다
위 6개 run에 대해:
```text
python3 scripts/verify-pipeline-run.py <run.json>
```
은 전부 PASS한다.
즉 verifier는 현재:
- evidence gate가 하나 존재하는지
- recorded exit가 0인지
등은 보지만,
> **S3/S5/S6가 계약에 적힌 `check_evidence.mjs <project> --repo`를 실제로 실행했는가**
까지는 강제하지 않는다.
그래서 계약보다 약한 명령을 기록해도 통과했다.
이 부분도 같이 막아야 한다.
권장:
- stage gate를 raw command 문자열만으로 보지 말고 semantic gate id를 둔다.
- 최소한 S3/S5/S6의 evidence gate는 `--repo` 존재를 검증한다.
- 사용자가 허용한 source-missing 예외를 도입한다면 exit 3 + UNVERIFIABLE 상태를 verifier가 이해하게 한다.
**검사기를 통과시키려고 관문을 약하게 만드는 경로를 차단해야 한다.**
---
# 6. 33 Record / 992 command 재검토의 “증거 범위”는 아직 약함
이전 리뷰는:
```text
33개 command-bearing Record
992 shell block
```
을 parser 수정 뒤 다시 분석하라고 했다.
현재 내용 자체는 내가 이번 검토에서 다시 전수 실행했고:
```text
reference mode:
records 33
blocks 992
findings 53
major 0
```
을 확인했다.
그래서 **현재 command 내용에서 새 major defect가 남았다고 보지는 않는다.**
다만 repository에 새 command review artifact가 남아 있는 것은 이번 remediation에서 다룬 일부 Record뿐이다.
새 schemaVersion 4 remediation 중 command block이 있는 Record:
```text
D-4
D-4a
A-7a
B-7a
B-6
```
즉 current reviewer artifact가 직접 남은 것은 **5 / 33 command-bearing Record**다.
나머지는 옛 schemaVersion 1/2 run만 있고, 그것은 parser가 labeled fence를 못 보던 시기의 영수증이다.
이전 리뷰는 historical ledger를 소급 조작하지 말라고 했으므로 옛 run을 고치면 안 된다.
대신 **프로젝트 단위 current command audit artifact**를 하나 남기는 편이 맞다.
예:
```text
reviews/2026-09-20-keycloak-session-store-command-audit.json
reviews/2026-09-20-keycloak-session-store-command-audit.md
```
여기에 33 Record 각각에 대해:
- source SHA256
- shellBlocks
- mode
- findings
- majorFindings
- minor finding disposition
- reviewer verdict
을 남긴다.
Record를 실제로 수정한 경우에만 새 remediation run을 만든다.
이렇게 하면 historical receipt를 위조하지 않으면서도 **“parser 수정 뒤 992개를 다시 봤다”**는 현재 증거가 남는다.
---
# 7. 현재 자동 검증 결과
## 프로젝트 gate
```text
verify-tech-log-tree PASS
verify-project-layout PASS (warn 존재)
audit-records PASS
check-figure-text PASS 31/31
check-figure-overlap PASS 31/31
check-figure-provenance PASS 31/31
check-required-content PASS 61
check-ssot-facts PASS
git diff --check PASS
```
## 문체
```text
prose 61/61 PASS
voice 61/61 PASS
```
## 전체 pipeline
```text
verify-pipeline.py
exit 0
```
parser가 수정되면서 전체 corpus도 이제 Record의 labeled shell fence를 실제로 세고 있다.
keycloak-session-store 전체(final SSOT + Record) 기준:
```text
shell blocks = 1920
findings = 150
```
이 수치가 이전보다 늘어난 것은 defect가 늘어난 것이 아니라 **전에 못 보던 labeled fence를 이제 보기 시작했기 때문**이다.
## 전체 unittest
```text
Ran 397 tests
OK
skipped=14
```
새 labeled-fence 관련 테스트도 통과한다.
---
# 8. 남은 작업 순서
## 1. evidence gate 우회부터 고친다
가장 먼저 한다.
- 기존 17:25 run 수정 금지
- `--repo`를 제거해 PASS시키는 방식 금지
- source missing을 명시적 `UNVERIFIABLE`로 보존할 수 있게 계약/verifier를 정리
- 또는 실제 source repo를 찾을 수 있다면 정본 경로로 대조
## 2. run verifier가 필수 evidence gate를 검증하게 한다
최소 S3/S5/S6에서:
```text
check_evidence.mjs <project> --repo
```
를 요구한다.
환경 예외가 있으면 명시적 상태로만 허용한다.
## 3. 33 Record command audit를 현재 artifact로 남긴다
- 992 block
- reference-mode 53 minor / 0 major
- minor의 문맥상 허용 여부
- 15 command-like text의 분류
를 프로젝트 단위 audit으로 남긴다.
실제 수정한 Record만 새 remediation run을 만든다.
## 4. SVG 잔여 context warning 7개를 마지막에 닫는다
current section은 이미 31/31 맞다.
남은 7개 previous/next snapshot만 모든 SSOT 수정 후 마지막에 regenerate/review한다.
## 5. 최종 검증
순서대로:
```text
project gates
→ verify-pipeline.py
→ unittest
```
---
# 9. 최종 판정
이전 리뷰의 **문서 내용 수정은 대부분 제대로 반영됐다.**
특히:
- parser
- Tree
- 문체
- 그림의 직접 SSOT 근거
는 제대로 개선됐다.
하지만 현재 remediation run 6개가 계약상 필수인 `--repo` evidence reconciliation을 생략한 채 PASS로 기록되어 있고, verifier도 그 우회를 잡지 못한다.
따라서 지금 상태는:
> **keycloak-session-store = 아직 더 봐야댐**
문서 내용보다 **검증 계약과 영수증의 진실성**을 한 번 더 고쳐야 한다.