docs: .env.example 런타임 시크릿 보완과 PEM 형식·기록 정정 - #108
Merged
Conversation
"런타임 5개 + bridge 1개 = 6개"로 적혀 있었으나 실제는 "런타임 8개 + bridge 1개
= 9개"다. 서술만 틀렸고 워크플로와 계약 테스트는 처음부터 9개를 고정하고 있었다 —
RuntimeSecretWorkflowContractTests의 containsExactlyElementsOf가 9개를 그대로
열거하므로, 기록과 통과하는 테스트가 서로 어긋난 상태였다.
보존 구역이라 숫자만 바꾸지 않고 "정정" 절을 추가해 무엇이 틀렸는지 남겼다
(implements/README "잘못 작성된 문서도 정정으로 처리").
세 숫자가 각각 다른 것을 세므로 함께 적었다. 안 적으면 다음 사람이 7과 9를 또
모순으로 읽는다.
- 9 — 워크플로가 action에 넘기는 env 전체
- 8 — 그중 런타임 키(bridge token 제외)
- 7 — 봉인 정책 infra/policy/sealedsecrets/back-prod.yaml이 요구하는 키
(PINLOG_AI_INTERNAL_SECRET과 bridge token 제외, back#105)
RuntimeSecretWorkflowContractTests 통과 확인
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
application.yml이 읽는 환경변수 13개 중 .env.example에는 6개만 있었다. 없으면 운영이 조용히 망가지는 JWT_PRIVATE_KEY가 목록에 없는 것이 가장 큰 구멍이었다. 넣은 것과 넣지 않은 것을 갈랐다. - JWT_PRIVATE_KEY — 운영 필수, 로컬 선택. 없으면 재시작마다 재로그인이다 - PINLOG_AI_INTERNAL_SECRET — 없으면 401을 삼켜 임베딩이 조용히 안 생긴다 - PINLOG_AI_BASE_URL·AUTH_CLIENT_REDIRECT_URI — 로컬 기본값이 정답이라 넣지 않았다 - PINLOG_AI_EMBEDDING_PROFILE — 비밀이 아니라 일부러 파일에 리터럴로 둔 값이다(BD-39). 예시에 올리면 "교체가 PR·리뷰를 거치게 한다"는 결정이 흐려진다 - DB_PASSWORD·BUILD_SHA — 운영·CI 전용 authentication.md 8장이 권하던 형식이 실제로 깨진다. 검증하다 발견했다. JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...-----END PRIVATE KEY-----" .env는 spring.config.import로 properties 형식으로 파싱되므로 따옴표가 구분자가 아니라 값의 일부가 된다. fromPem이 지우는 것은 공백뿐이라 그 문자가 살아남아 Illegal base64 character 22(0x22 = ")로 디코딩이 실패한다. 같은 파서가 \n은 실제 개행으로 되돌리므로 개행 표기 자체는 맞았다 — 따옴표만 문제다. 실측으로 확인했다. 같은 값을 따옴표 있는 형태와 없는 형태로 .env에 넣고 Properties.load 후 fromPem의 정리 과정을 그대로 적용했다. QUOTED: firstChar=0x22 → decode FAIL: Illegal base64 character 22 BARE: firstChar=0x2d → decode OK 두 곳(.env.example, authentication.md)을 바로잡고 운영 Secret은 반대로 실제 개행을 넣는다는 것도 함께 적었다 — 두 경로가 다르다는 것이 혼동의 원인이다. 코드는 문제가 없다. JwtKeyProviderTest.readsInjectedPemAndDerivesPublicKey가 실제 개행이 든 PEM을 이미 고정하고 있어 받아들이는 형식은 검증돼 있었고, 틀린 것은 적어 둔 예시뿐이다. Co-Authored-By: Claude Opus 5 (1M context) <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.
요약
.env.example에JWT_PRIVATE_KEY와PINLOG_AI_INTERNAL_SECRET을 추가한다. 그 과정에서authentication.md가 안내하던.env값 형식이 실제로 동작하지 않는 것을 발견해 함께 고쳤다.BI-26의 Secret 개수 오기도 정정한다.Jira (필수)
BI-19(back#58)·BI-01(back#12)처럼 이슈만 참조한 기록들이다관련 GitHub Issue (선택)
변경 사항
.env.example—JWT_PRIVATE_KEY·PINLOG_AI_INTERNAL_SECRET추가(주석 상태). 없을 때의 동작과 값 형식을 함께 적었다docs/development/authentication.md— 8장의.env예시에서 따옴표 제거 + 이유 서술. 운영 Secret은 반대로 실제 개행을 넣는다는 것도 명시docs/backend/implements/BI-26-...md— Secret 개수를6개→9개로 정정하고 "정정" 절 추가테스트 / 검증
./gradlew clean check --no-daemon— 394개 통과, 실패 0, 오류 0소스 변경이 없으므로 RED/GREEN 사이클은 없다. 대신 실측 두 건으로 검증했다.
①
.env값 형식 — 따옴표가 깨진다Properties.load후JwtKeyProvider.fromPem의 정리 과정(fromPem,JwtKeyProvider.java:62-66)을 그대로 적용해 두 형태를 비교했다..env는spring.config.import: optional:file:.env[.properties]로 properties 형식으로 파싱되므로 따옴표가 구분자가 아니라 값의 일부가 된다.fromPem이 지우는 것은 공백뿐이라 그 문자가 살아남아 base64 디코딩이 실패한다. 같은 파서가\n은 실제 개행으로 되돌리므로 개행 표기 자체는 맞았고 따옴표만 문제였다.② 로그인 3사 E2E — 이메일 필수화 이후에도 정상
#103(이메일NOT NULL) 머지분 위에서 실제 브라우저로 3사 로그인을 완료했다.V6마이그레이션email is_nullable = NOOAUTH_FAILED)member·social_account@kakao.com·@naver.com·@gmail.com)scope도 함께 확인했다 — Googleopenid email· Kakaoaccount_email· Naveremail. 이메일 필수화의 전제(공급자가 실제로 이메일을 준다)가 실측으로 성립한다.배경
application.yml이 읽는 환경변수 13개 중.env.example에는 6개만 있었다. 없으면 운영이 조용히 망가지는JWT_PRIVATE_KEY가 목록에 없는 것이 가장 큰 구멍이었다.넣은 것과 넣지 않은 것을 갈랐다.
JWT_PRIVATE_KEYPINLOG_AI_INTERNAL_SECRETPINLOG_AI_BASE_URL·AUTH_CLIENT_REDIRECT_URIPINLOG_AI_EMBEDDING_PROFILEDB_PASSWORD·BUILD_SHA이 판단의 근거가 기동 로그에서 그대로 확인됐다. 로컬 기동 시 뜨는 경고 두 개가 추가한 두 키와 정확히 일치한다.
리뷰 포인트
두 값이 소셜 로그인 자격증명과 반대라는 것을 예시에 적었다.
KAKAO_CLIENT_ID=는 빈 값이면 기동이 실패하지만(BT-05), 이 둘은 기본값이 빈 문자열이라 "정의했지만 비었다"와 "정의하지 않았다"가 같은 결과로 수렴한다. 기존 경고문이 "빈 값으로 두면 안 된다"로 뭉뚱그려져 있어 반대 사례를 명시하지 않으면 오해를 낳는다.BI-26은 보존 구역이라 숫자만 바꾸지 않았다. "정정" 절을 추가해 무엇이 틀렸고 근거가 무엇인지 남겼다(implements/README— "잘못 작성된 문서도 정정으로 처리"). 세 숫자가 각각 다른 것을 세므로 함께 적었다 — 안 적으면 다음 사람이7과9를 또 모순으로 읽는다.infra/policy/sealedsecrets/back-prod.yaml이 요구하는 키BI-26은 내 기록이 아니다(chore(S15P11A705-154): add runtime secret handoff workflow #100, @tpals0409). 정정 내용에 이견이 있으면 알려 주면 좋겠다 — 코드는 문제가 없고 서술만 틀린 건이다.미결 / 후속
ux_social_account_provider_user중복이 잡히고social account created concurrently, retrying once후 정상 가입했다(26ms 차). 부분 유니크가 설계대로 막은 것이고 결과에 중복 행은 없다. 브라우저가 콜백을 두 번 보냈을 가능성이 유력하지만 원인을 특정하지 못했다 — 이 PR 범위 밖이고, 재현된 것이 처음이라 기록만 남긴다.env.example에 검증 테스트가 없다.application.yml이 읽는 변수와 예시 파일이 어긋나는 것을 사람이 대조해야 발견한다 — 이번이 그 사례다. 계약 테스트로 고정할 만하지만 별건이다