Repository navigation
fix(ruby): JwksStore::JWKS_MAX_AGE_SECONDS 를 게시 전에 private_constant 로 — 1.4.1 을 patch 로 - #914
Merged
Merged
Conversation
… — 1.4.0 이후 생긴 유일한 공개 표면이라 1.4.1 을 patch 로 지킨다 키셋 수명 상수(#881–#900 에서 추가)가 ruby 에서만 공개 상수였다. 나머지 여덟은 비공개다 — go `jwksMaxAgeSeconds`(소문자) · .NET `internal const` · kotlin `internal const val` · php `private const` · java package-private `static final` · rust 비-pub `const` · node 비-export `const` · python `_internal` 모듈. 공개로 게시하면 상수 하나가 계약이 되어 이번 릴리스가 minor 가 되고, 나중에 지우면 major 다(선례 #854 · ruby 1.3.1). 계측(리플렉션 워커 — `Module#constants` 기반이라 private_constant 를 뺀다. yard 는 private_constant 모듈을 공개로 센다): - 양성 대조 1.3.2 → 1.4.0: Http.settling · Http.read_error_body 추가가 보인다 - 음성 대조 1.4.0 → 1.4.0: 0 줄 - 판정 1.4.0 → main(5bc8bd3): `> CONST KeycloakSdk::JwksStore::JWKS_MAX_AGE_SECONDS` 한 줄 - 이 커밋 1.4.0 → fix: 0 줄 · main → fix: `< CONST KeycloakSdk::JwksStore::JWKS_MAX_AGE_SECONDS` 한 줄 TDD: - RED(수정 전): expected [:JWKS_MAX_BYTES, :FAILURE_BACKOFF_BASE, :JWKS_MAX_AGE_SECONDS, :FAILURE_BACKOFF_CAP] not to include :JWKS_MAX_AGE_SECONDS - GREEN: bundle exec rspec → 605 examples, 0 failures · rubocop → no offenses - scripts/test/test-security-defaults.sh → 487 passed, 0 failed (수명 축은 원문의 `= <숫자>` 선언을 읽는다 — 새 `private_constant` 줄은 SD_TC_DECL 에 걸리지 않아 선언 수는 그대로 1) [no-changelog: 게시 전 공개 범위 축소 — 1.4.0 이후 추가돼 미게시, 소비자 영향 없음] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R4jYS4tpj7usahf8MK5dXo
|
xzawed
added a commit
that referenced
this pull request
Oct 31, 2026
…4 · rust 1.1.5 · kotlin 1.0.8 · python·dotnet·node 1.0.7 (#916) DEPLOY.md §4 step 1 — 태그 **전** 커밋(틀: 57a112c/#855, PHP 자리는 8c7ba42/#851). SSOT·매니페스트·랜딩 README·함대 문서· CHANGELOG 절과 그 회전을 한 커밋에서 옮긴다. 바탕은 3ca15f3(#915 — [Unreleased] PHP 항목의 마지막 문장을 바로잡았다; 옮긴 항목은 그 바이트다). `.github/release-request.json` 은 건드리지 않았다(이 커밋은 태그를 자르지 않는다). `df_api_baseline` 과 기준선 사본 (`japicmp.baseline` · kotlin·python·php·ruby·node CI · `PackageValidationBaselineVersion`)도 그대로다 — 기준선은 게시 확인 뒤 (step 9)에만 움직인다. 번호는 PM 결정이다 — 아홉 모두 patch, 날짜는 모두 2026-10-31. 판정 근거(PM 이 넘긴 것): - java 1.2.4 (patch) — v1.2.3..: 바뀐 출하 파일 15(주석만 9) · `public` 이 든 추가 줄 4 는 전부 패키지 전용 클래스의 멤버(AdminEngine 의 중첩 Exchange/Settled · BoundedTransport 안 익명 클래스) · 공개 JwtValidator 에는 패키지 전용·private 멤버만 늘었다 · TokenResponseGuard 는 패키지 전용 · 공개 타입의 interface/record/enum 변화 0.⚠️ PM 의 첫 추출은 pathspec `java/*/src/main` 이 파일 0 개와 맞아 눈멀었다(kotlin 대조 12 = 12) — `:(glob)java/*/src/main/**` 로 다시 쟀다. - kotlin 1.0.8 (patch) — kotlin-v1.0.7..: `public` 선언 줄 추가·삭제 0(explicitApi). - python 1.0.7 (patch) — 추가·삭제된 def/class 는 전부 `_internal/` 아래이거나 중첩 함수 · `keycloak_sdk`·`keycloak_sdk.aio` 의 `__all__` 이 py-v1.0.6 과 바이트 동일. - node 1.0.7 (patch) — 후보는 `sendableBearer`(token-provider.ts, 문서 주석만) 하나이고 index 가 다시 내보내지 않는다(package.json `exports` 는 "." 하나). - go 1.2.5 (patch) — 후보는 전부 `_test.go` 이거나 비공개(`tieCtx`) · 비시험 파일의 exported 식별자 추가·삭제 0. - dotnet 1.0.7 (patch) — `public override` 4 줄은 전부 `internal sealed` 클래스(ColdStart/ForcedRefetch ConfigurationManager) 안. - php 1.5.1 (patch) — 새 `final class BearerToken` 은 php/src/Internal 아래이고 `@internal`. - rust 1.1.5 (patch) — rust/src 의 `pub` 항목 추가·삭제 0. - ruby 1.4.1 (patch) — 반영 워커(대조: 1.3.2→1.4.0 은 알려진 추가 둘 · 1.4.0→1.4.0 은 0). 1.4.0→main 에 `JwksStore::JWKS_MAX_AGE_SECONDS` 하나가 보였고 #914 가 private_constant 로 만든 뒤 1.4.0→main(d7d353a) = 0. - 사실만 받은 독립 Grok 레그가 같은 아홉 번호에 닿았다(java 는 바로잡은 사실로 다시 물어 PATCH). Grok 의 이견 — 동작 변경(JWKS 300 초 fail-closed · 응답 전체 기한 · python 바이트 예산 · Bearer 문법)은 patch 가 아니어야 한다 — 은 DEPLOY §4 step 0(게시된 API 표면 기준 SemVer)과 선례(여섯째 물결이 새 거부 — 256,000 B 토큰 상한 — 를 여섯 레인에서 patch 로 냈고, minor 는 공개 상수가 늘어난 PHP 1.5.0 뿐)로 patch 유지. Grok 이 든 구체 시나리오(`=` 패딩 거부)는 소유자가 반증했다 — ruby bearer_grammar_spec `pad: sends "abc=="`(84 examples, 0 failures), 같은 "pad" 행이 go·node·dotnet·kotlin·php·java 표에도 있다. 다시 확인(이 커밋 — 태그 이후 매니페스트 diff, 끝점 3ca15f3): pyproject.toml(py-v1.0.6) · package.json(node-v1.0.6) · go.mod (go/v1.2.4) · Cargo.toml(rust-v1.1.4) · keycloak-sdk.gemspec(ruby-v1.4.0) · kotlin/build.gradle.kts(kotlin-v1.0.7) 0 줄. csproj (dotnet-v1.0.6) 3 줄 — 기준선 1.0.5 → 1.0.6(여섯째 물결 step 9) · DependencyInjection.Abstractions 9.0.21 → 9.0.22 · SourceLink 10.0.402 → 10.0.403(빌드 전용, 둘 다 dependabot #906). java pom 둘(v1.2.3) 4 줄 — japicmp.baseline 1.2.2 → 1.2.3(step 9) · surefire·failsafe 3.6.0 → 3.6.1 · jacoco 0.8.15 → 0.8.16(빌드 플러그인). php/composer.json(php-v1.5.0) — `ext-curl` · guzzle `^7.15.2` · psr7 `^2.12.3`(#884 — PHP Changed 항목이 적는 것). node lock 의 런타임 셋은 node-v1.0.6 과 같다(admin-client 26.8.1 · openid-client 6.8.8 · jose 6.2.13). 바꾼 것: - SSOT: scripts/lib/deploy-facts.sh — df_published_version 아홉 값(df_api_baseline 그대로). - 매니페스트: python/pyproject.toml · node/package.json · node/package-lock.json(루트 두 줄, 손으로) · rust/Cargo.toml · rust/Cargo.lock(`keycloak-sdk` 항목) · ruby/lib/keycloak_sdk/version.rb · ruby/Gemfile.lock(PATH 한 줄) · kotlin/build.gradle.kts · dotnet csproj `<Version>` 1.0.6 → 1.0.7(PackageValidationBaselineVersion 1.0.6 그대로). go·php·java 는 편집 없음(태그가 SSOT · php/composer.json 에 version 키 없음 · java POM 은 1.0.0-SNAPSHOT). - 하네스: harness/apps/kotlin/build.gradle.kts 1.0.8(주석 + 선언) · harness/apps/rust/Cargo.lock `keycloak-sdk` 1.1.5. check-versions 가 그 밖에 요구한 자리 0. - 아홉 <lang>/README.md(레지스트리 랜딩): 새 배너(버전 · 설치 해석 · 이번 릴리스 요약). 요약은 그 언어의 [Unreleased] 항목(태그가 그 언어를 이름한 것 — 여러 언어 · `(전 언어)` 항목 포함)에서만 옮겼고 항목이 단⚠️ 행동 변화는 전부 옮겼다(Bearer 규칙과 그 언어의 끝 개행·그랜트 거부 갈래 · JWKS 300 초 · 기한 Changed · ruby rack-oauth2 · php ext-curl · python 바이트 예산 · node·python 메시지). 배너 숫자는 의존 핀을 빼고 전부 그 언어 항목 안에 있다(banner_numbers.py — 내용부만, 상투 머리·꼬리 · 버전 · .NET 의 DependencyInjection.Abstractions 핀 제외 → 아홉 모두 미추적 0, 대조군: 4,321 을 넣은 사본 → UNTRACED 1). 지금 배너는 「`<old>` was a … release」 문단으로 내렸다 — node 는 틀(#812 · #855)대로 과거완료/「Since then」, 나머지 여덟은 머리만 바꾸고 새 배너로 옮긴 상투 문장만 뺐다(demote 토큰 diff: php·ruby·java·rust·kotlin·dotnet 비동일 구간 2 · go·python 3 · node 22 = 시제만). 설치 펜스/핀: java 둘 · kotlin · go · node. 같은 부류 자리(가드 밖): go Requirements 「for the published」 · go Install 「The go/vX tag is published」 · kotlin Requirements 「published」 · 「The published … reuses」 · node 「A bare install resolves」. 아홉 README 의 한글 0 · 배너의 "not yet" 0. - PHP(#915 의 측정 — Composer 2.10.3 · PHP 8.3.36, ext-curl 대역 `ext-kcsdkprobe` 를 요구하는 판으로): 배너 머리 「where `ext-curl` is enabled, `composer require …` resolves `1.5.1`」 ·⚠️ 문장은 셋으로 — 제약 없는 require 는 경고만 내고 `1.5.0` 을 설치(종료 코드 0), `1.5.1` 을 지정한 제약은 거부(`Your requirements could not be resolved …`), `1.5.1` 이 든 lock 의 `composer install` 도 거부(`Your lock file does not contain a compatible set of packages …`). 경고는 측정이 대역 패키지라 글자로 인용하지 않고 풀어 썼다. Requirements 의 ext-curl 줄에 「without the extension a bare `composer require xzawed/keycloak-sdk` stays on `1.5.0`」. - .NET: 1.0.5 선례(내린 문단의 「The package now depends on `Microsoft.Extensions.DependencyInjection.Abstractions` 9.0.21 or later (it was 9.0.20).」)대로 「… 9.0.22 or later (it was 9.0.21).」 — csproj 는 dotnet-v1.0.6 에서 9.0.21, 이 트리에서 9.0.22(#906). - 함대 문장(일곱 갈래, 번호 내림차순 — 순서 그대로): README.md · README.ko.md · SECURITY.md · getting-started. 가드가 요구한 그 밖의 자리: CLAUDE.md 현재 상태 표 · DEPLOY.md `- Install:` 셋 · compatibility.md 아홉 행 · language-support 매트릭스 · getting-started 설치 헤딩 아홉과 `### 3)` 펜스 · README 영·한 Install 펜스(go · java · kotlin). 가드 밖 같은 부류 자리: compatibility 주석의 `go/v1.2.5` · getting-started 의 「is live」 여덟 · 「resolves」 넷 · java BOM 좌표 · go 「is published」 · php 「serve `v1.5.1` today」 · kotlin 로컬 좌표 셋(`### 2)` 의 jar 이름 · mavenLocal 선언 · `~/.m2` 경로 — 매니페스트가 1.0.8) · php·ruby 「a minor release」 → 「a patch release」 · php 「now resolves `1.5.1` where `ext-curl` is enabled (else `1.5.0`)」. getting-started 는 doc-budget 43,553 B 에 여유가 0 이라 그 한정(+43 B)을 같은 문단의 정보 없는 말 둘로 맞바꿨다 — 「How publishing works here: 」(27 B) · 「, and it never could」(20 B). 원문 46,788 → 46,784 B · 래칫 인상 0. 나머지 함대 문서 일곱의 바이트 크기 변화 0. - CHANGELOG: [Unreleased] 의 36 항목(Changed 12 · Fixed 6 · Security 18)을 일곱 절로 — 여러 언어를 이름한 항목은 절 제목의 언어 목록이 항목 태그와 겹치는 절마다 바이트 그대로 되풀이했다(선례: changelog/2026-09.md 의 2026-09-26 첫 물결 머리말 「여러 언어를 이름한 항목은 해당하는 절마다 그대로 되풀이했습니다」) — `(전 언어)` 둘은 일곱 절 모두에. 60 줄(36 개): [1.5.1] (PHP) 6 · [1.4.1] (Ruby) 9 · [1.2.5] (Go) 6 · [1.2.4] (Java) 7 · [1.1.5] (Rust) 6 · [1.0.8] (Kotlin) 7 · [1.0.7] (Python · .NET · Node) 19. 절 안은 기준의 ### 범주 순서와 항목 순서 그대로. 첫 절 머리말(문단 넷: 무엇이 실리는가 · 번호와 왜 모두 patch 인가 · 되풀이 규칙과 그 선례, 되풀이한 항목 안 「아래」·「위」의 뜻 · 같은 번호의 앞 절 셋 `[1.4.1] - 2026-10-23 (PHP)` · `[1.2.4] - 2026-10-27 (Go)` · `[1.0.7] - 2026-10-27 (Kotlin)` 은 모두 보관본 2026-10, 앞 절이 없는 넷 · df_published_version 포인터), 나머지 여섯에 한 줄 머리 ([1.0.7] 에는 .NET 키 회전 항목의 「last-known-good 은 그대로」 — 05fe878 가 먼저, 그것을 끈 .NET Security 항목은 c7b0eb4 로 뒤에 착지). 되풀이로 Python 「위 줄의 본문 기한」은 [1.0.7] 안에서 다시 바로 위 줄을 가리킨다. PM 의 첫 지시는 선례를 「첫 교차 절」로 잘못 적었다 — 실제 선례(2026-09-26)는 되풀이이고, 그 규칙이 66179cf 을 46 = 46 으로 재현한다. (구현자 쪽 재생: check_move2.py wave1 — 66179cf^ 의 [Unreleased] 37 항목 → 기대 배치 46 · 66179cf 의 세 절 실제 46 · 배치 어긋남 0.) - 회전: 되풀이로 루트가 76,866 B(> 65,536)라 `node scripts/changelog-rotate.mjs --dry-run` → 계획 「76866B → 39227B — 날짜 1개 · 절 7개: 2026-10-27」 → 실행 같은 줄 → 다시 실행 「39227B ≤ 65536B — 옮길 것이 없다」. 옮긴 것: 2026-10-27 묶음 일곱 절 — [1.4.0] (Ruby) · [1.2.4] (Go) · [1.2.3] (Java) · [1.1.4] (Rust) · [1.0.7] (Kotlin) · [1.0.6] (Python · .NET · Node) · [1.5.0] (PHP), 37,639 B → changelog/2026-10.md(126,322 → 163,961 B · 절 20 → 27). 옮긴 꼬리에 상대 링크가 없어 「한 단계 위」로 고친 링크 0. 2026-08 · 2026-09 보관본은 바이트 그대로. 루트는 이제 [Unreleased] 와 2026-10-31 일곱 절뿐이다. - 옮기기: move2.mjs — Edit 툴을 거치지 않고 기준 blob(3ca15f3)을 Buffer 줄 단위로 복사한다. 절 머리 글은 sections2.json. - 검사(독립 — Python, 바이너리 I/O, sections*.json 도 옮기기·회전 코드도 읽지 않고 기대 제목 일곱을 스스로 고정): check_move2.py wave7 — LF · UTF-8 · 루트 머리(1,476 B) 바이트 동일 · [Unreleased] 내용 줄 39 → 0 · 일곱 제목 뒤 루트에 다른 절 없음 · 항목마다 겹치는 절 각각에 바이트 그대로 정확히 1 회 · 겹치지 않는 절에 0 회 · 같은 ### 범주 · (절, 범주) 안 상대 순서 · 절 안 범주 순서 · 덧붙은 항목 0 · 2026-10 보관본 = 옛 머리 + 옛 루트 꼬리(상대 링크 한 단계 위) + 옛 본문 → RESULT: OK(60 줄 · 36 개). - 음성 대조: 작업본에서 Go 절의 `(전 언어)` JWKS 줄 한 바이트(300 → 301) → MISMATCH(3, exit 1) → 복원(cmp 동일) → OK. 사본 여덟(Go 절에서 되풀이 하나 빼기 · Go 항목을 Rust 절에 · 범주 안 순서 · 범주 바꿈 · 보관본 한 바이트 · 루트 머리 한 바이트 · 옮긴 절을 루트에도 남김 · [Unreleased] 에 항목 남김) — 여덟 모두 MISMATCH(exit 1). check-docs 8d 가 보존(main 대비)을 다시 봤다(아래). 하지 않은 것: df_api_baseline 과 기준선 사본(step 9) · .github/release-request.json · 태그 · push · PR · scripts/test/fixtures/** · doc-budget 인상. 틀과 다른 것 · PM 판단이 필요한 것: - PHP 1.5.0 배너를 지시대로 내렸다(틀 57a112c 와 같다). PHP 1.5.0 범프(8c7ba42)는 1.4.1 배너를 내리지 않고 갈아치웠다. - 배너에서 항목을 좁힌 곳: 응답 기한의 「디스커버리」는 .NET 배너에만(소스에서 well-known 을 받는 것은 dotnet JwtValidator.cs 하나) · JVM 배너는 33.6 초만(「1 초 설정에 7 초」는 JVM 값으로 적히지 않았다) · .NET 배너의 「그대로」 목록에서 last-known-good 을 뺐다(위 착지 순서) · node 배너는 옛 한글 메시지를 인용하지 않고 「which was in Korean」으로 썼다(README 한글 0 유지). 「No public API changed」는 아홉 배너 모두 — PM 판정 근거가 출처다. 함정: core.autocrlf=true(시스템 · 전역)라 eol 속성 없는 파일 아홉(csproj · build.gradle.kts 둘 · Cargo.lock 둘 · Cargo.toml · package.json · package-lock.json · pyproject.toml)이 체크아웃마다 작업본 CRLF 가 된다 — 처음 체크아웃에서도, 3ca15f3 로 rebase 한 뒤에도 그랬다. 두 번 다 바이트 단위로 CRLF → LF(crlf_to_lf.py)로 돌렸고 그 아홉의 diff 는 바이트 동일했다. rebase 의 CHANGELOG 충돌은 main 의 것을 받고 새 기준 blob 에서 옮기기를 다시 돌렸다. node lock 은 `--package-lock-only` 를 쓰지 않고 루트 두 줄만 Edit 로. Docker 마운트는 MSYS_NO_PATHCONV=1 이 있어야 `-w /w` 가 `W:/` 로 바뀌지 않았다. python -c 에 한글 리터럴을 넣으면 명령줄이 cp949 로 깨진다 — 대조 스크립트의 앵커는 바이트/ASCII 로 바꿨다. MSYS_NO_PATHCONV=1 docker run --rm -v <wtbump>:/w -w /w debian:bookworm sh -c 'LANG= LC_ALL= dash scripts/test/test-publication-claims.sh' 손대지 않은 트리 241 passed, 0 failed → SSOT 만 옮긴 트리 172 passed, 69 failed → 이 트리(3ca15f3 위) 241 passed, 0 failed node scripts/check-docs.mjs . --strict --min-facts=78 --min-anchors=26 --min-anchor-links=24 --min-blob-refs=5 --min-count-anchors=4 → 한정을 처음 넣었을 때 exit 1(getting-started 적재 43658B > doc-budget 43553B) → 맞바꾼 뒤 exit 0 · 78 facts · 26 anchors · 31 anchor links · 66 self-blob targets · 12 archive blob refs (고유 9) · 8d 대조: Go 머리 문단에 901 B → 「항목 1082B > 1024B」 node scripts/check-versions.mjs exit 0(경고 1건 — 기저 버전 갈림, 차단 안 함) · cd rust && cargo metadata --locked --offline exit 0 sh scripts/test/test-changelog-ledger.sh 68/0 · test-deploy-facts 184/0 · test-check-versions 99/0 · test-readme-mirror 7/0 · test-readme-badges 24/0 · test-security-defaults 487/0 · git diff --check 0 · 바뀐 31 파일 git ls-files --eol 전부 i/lf w/lf 「가드 밖」 판정 확인(이 트리의 추적 파일 사본): 가드 밖이라 적은 24 자리를 전부 되돌려도 publication-claims 241/0 — 대조로 그 사본의 python 설치 헤딩 하나를 더 되돌리면 240/1. 사본은 지웠다. test-changelog-landing.sh(커밋 뒤, merge-base 3ca15f3) 15/0 — 면제 표식 1 건, 게시 소스 1 개(ruby/lib/keycloak_sdk/version.rb) [no-changelog: 버전 범프 — [Unreleased] 를 일곱 절로 옮겼다] Claude-Session: https://claude.ai/code/session_01R4jYS4tpj7usahf8MK5dXo Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



무엇
KeycloakSdk::JwksStore::JWKS_MAX_AGE_SECONDS(키셋 수명 300 초, #881–#900 에서 추가)를private_constant로 좁힌다. 릴리스 웨이브 7 의 버전 판정에서 ruby 의 1.4.0 이후 유일한 공개 표면 추가로 잡혔다.왜
internal· phpprivate const· java package-private · rust 비-pub · node 비-export · python_internal).[no-changelog: …].근거
Http.settling·Http.read_error_body추가가 보인다> CONST KeycloakSdk::JwksStore::JWKS_MAX_AGE_SECONDS1 줄< CONST …::JWKS_MAX_AGE_SECONDS1 줄expected [...:JWKS_MAX_AGE_SECONDS...] not to include :JWKS_MAX_AGE_SECONDSscripts/test/test-security-defaults.sh= <숫자>선언을 읽어 영향 없음)🤖 Generated with Claude Code
https://claude.ai/code/session_01R4jYS4tpj7usahf8MK5dXo