Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
908 commits
Select commit Hold shift + click to select a range
e355155
fix(core): 초성 점프 인덱스를 렌더되는 행에서 파생 (#939)
OnlyReadOneBook Sep 13, 2026
8ec6c43
fix(platform): predictive back 진행 중 앞 화면을 축소해 겹침을 푼다 (#1869)
OnlyReadOneBook Sep 13, 2026
b1b7556
docs(platform): versionCode 를 두 채널 대역으로 가르고 승격을 금지한다
OnlyReadOneBook Sep 13, 2026
1b67779
test(core): 타이포 B/R 동일성 잠금을 TextStyle 전체 비교로 닫는다 (#2061)
OnlyReadOneBook Sep 13, 2026
8b0ee51
docs(core): Bold 하한이 닫는 범위를 제목 크기까지 정확히 적는다
OnlyReadOneBook Sep 13, 2026
22f99ae
docs(afternote): 비선택 탭 주석의 대비 수치와 결정 주체를 현행으로 고친다 (#2059)
OnlyReadOneBook Sep 13, 2026
4d90c4d
fix(platform): 스택 안내 코멘트에 pull-requests 쓰기 권한을 준다 (#2068)
OnlyReadOneBook Sep 13, 2026
ce55950
fix(core): 플러스 배지 원 색을 시안 토큰 gray9 로 맞춘다 (#2063)
OnlyReadOneBook Sep 13, 2026
c404122
test: update screenshot baselines in CI
github-actions[bot] Sep 13, 2026
2e2acd0
maintenance(platform): base 브랜치 삭제로 닫힌 PR 을 되살린다 (#2076)
OnlyReadOneBook Sep 13, 2026
2c720e8
Merge pull request #2077 from Afternote/maintenance/2076-delete-reope…
OnlyReadOneBook Sep 13, 2026
7d87aa3
Merge pull request #2070 from Afternote/fix/2068-stack-notify-permission
OnlyReadOneBook Sep 13, 2026
0e9bb13
Merge remote-tracking branch 'origin/develop' into feat/1762-draft-re…
OnlyReadOneBook Sep 13, 2026
2010009
refactor(afternote): 임시저장 목록 축을 걷어내고 조회 분리만 남긴다
OnlyReadOneBook Sep 13, 2026
880b64b
fix(ci): pr-open 라벨러가 본문의 Closes 를 함께 읽게 한다 (#2082)
OnlyReadOneBook Sep 13, 2026
b4abeb6
fix(setting): 설정의 비밀번호 변경 목적지를 연결한다 (#2083)
OnlyReadOneBook Sep 13, 2026
3ed4af2
fix(setting): 수신자 목록 0건에 안내와 등록 진입점을 그린다 (#2086)
OnlyReadOneBook Sep 13, 2026
440a576
fix(core): 업로드 파일 크기 초과(1803)를 도메인 실패 타입으로 번역한다 (#2089)
OnlyReadOneBook Sep 13, 2026
4f57e70
fix(afternote): 곡 없는 임시저장을 발행 상세와 분리해 조회한다 (#1745)
OnlyReadOneBook Sep 13, 2026
ec746d0
Merge branch 'feat/1745-draft-detail' into feat/1762-draft-resume
OnlyReadOneBook Sep 13, 2026
8ea5a94
Merge remote-tracking branch 'origin/feat/1762-draft-resume' into fix…
OnlyReadOneBook Sep 13, 2026
ba6f3d9
docs(afternote): initialLoadSize 를 한 페이지로 낮춘 이유를 적는다 (#1762)
OnlyReadOneBook Sep 13, 2026
0cb479c
docs(afternote): initialLoadSize 주석의 영향 서술을 실제 동작으로 좁힌다 (#1762)
OnlyReadOneBook Sep 13, 2026
954e53f
docs(afternote): initialLoadSize 주석에서 없는 동작 차이를 걷어낸다 (#1762)
OnlyReadOneBook Sep 13, 2026
46c0e2a
refactor(afternote): 동작을 바꾸지 않는 initialLoadSize 지정을 걷어낸다 (#1762)
OnlyReadOneBook Sep 13, 2026
50aaf6e
Merge pull request #1985 from Afternote/feat/1762-draft-resume
OnlyReadOneBook Sep 13, 2026
91c7a7d
fix(home): 큰 글씨·긴 이름에서 한마디 작성일이 한 글자씩 세로로 서는 것을 막는다 (#2032)
Sadturtleman Sep 14, 2026
077eb96
fix(mindrecord): 정식 일기 수정도 대상을 못 읽었으면 저장을 막는다 (#2027)
Sadturtleman Sep 14, 2026
a12917b
fix(mindrecord): 답변 수정의 조회 실패 복구가 대상을 오늘 질문으로 바꾸지 않게 한다 (#2028)
Sadturtleman Sep 14, 2026
98277fd
fix(mindrecord): 진행 중인 첨부를 수로 세어 저장 잠금이 어긋나지 않게 한다 (#2029)
Sadturtleman Sep 14, 2026
97814ac
fix(mindrecord): 늦게 도착한 수정 프리필이 작성 중 입력을 덮지 않게 한다 (#2031)
Sadturtleman Sep 14, 2026
a254d83
fix(onboarding): 아이디 찾기 인증번호 발송·확인을 진행 중인 Job 으로 막는다 (#1864)
Sadturtleman Sep 11, 2026
4b82335
fix(onboarding): 인증 결과가 자기가 검증한 입력에만 적용되게 한다 (#2025)
Sadturtleman Sep 14, 2026
7f16262
fix(onboarding): 가입 부분 성공 복구를 실제로 만들어진 계정에 귀속한다 (#2026)
Sadturtleman Sep 14, 2026
a087592
refactor(onboarding): 이메일 형식 검사를 OnboardingEmailRule 로 모은다 (#1851)
Sadturtleman Sep 14, 2026
510941c
chore(deps): bump the github-actions-updates group with 3 updates
dependabot[bot] Sep 14, 2026
42c5105
refactor(onboarding): 실패 사유와 표시 채널을 분리한다 (#1863)
OnlyReadOneBook Sep 8, 2026
12d1743
refactor(onboarding): place popup consumption with recovery flow cons…
OnlyReadOneBook Sep 8, 2026
d70a2b2
chore: 옛 guard check-run 을 걷어내려 HEAD 를 갱신한다 (#1983)
OnlyReadOneBook Sep 11, 2026
03bdb79
Merge pull request #1963 from Afternote/refactor/1863-onboarding-failure
Sadturtleman Sep 15, 2026
0a6cede
Merge remote-tracking branch 'origin/refactor/1863-onboarding-failure…
Sadturtleman Sep 15, 2026
6c3799a
Merge remote-tracking branch 'origin/develop' into rebase/1802
Sadturtleman Sep 15, 2026
a824aea
Merge pull request #1825 from Afternote/refactor/1802-onboarding-mvi
Sadturtleman Sep 15, 2026
badebd4
Merge remote-tracking branch 'origin/develop' into refactor/1809-noti…
OnlyReadOneBook Sep 18, 2026
979ed9d
Merge pull request #2013 from Afternote/security/1166-passkey-crypto
OnlyReadOneBook Sep 18, 2026
807a922
Merge pull request #2014 from Afternote/fix/1871-debug-kakao-diagnostics
OnlyReadOneBook Sep 18, 2026
2cba415
Merge pull request #2095 from Afternote/feat/1745-draft-detail
OnlyReadOneBook Sep 19, 2026
8f162b0
Merge pull request #2092 from Afternote/fix/2086-receiver-empty-state
OnlyReadOneBook Sep 19, 2026
ef43a4e
Merge pull request #2091 from Afternote/fix/2082-labeler-multi-issue
OnlyReadOneBook Sep 19, 2026
5317a87
Merge pull request #2090 from Afternote/fix/2089-upload-size-failure-…
OnlyReadOneBook Sep 19, 2026
c8451bf
Merge pull request #2066 from Afternote/test/2061-typography-pair-lock
OnlyReadOneBook Sep 19, 2026
041ec1e
Merge pull request #2065 from Afternote/docs/2059-type-filter-comment
OnlyReadOneBook Sep 19, 2026
9ab2328
Merge pull request #2058 from Afternote/fix/1869-predictive-back
OnlyReadOneBook Sep 19, 2026
46d63b1
Merge pull request #2056 from Afternote/test/709-receiver-create-refresh
OnlyReadOneBook Sep 19, 2026
df7287c
Merge pull request #2048 from Afternote/refactor/934-receiver-failure…
OnlyReadOneBook Sep 19, 2026
618872d
Merge pull request #2023 from Afternote/refactor/1305-setting-jvm
OnlyReadOneBook Sep 19, 2026
e504d84
Merge pull request #2020 from Afternote/refactor/2017-core-failure-tr…
OnlyReadOneBook Sep 19, 2026
9f12f8a
Merge remote-tracking branch 'origin/develop' into refactor/1396-sett…
OnlyReadOneBook Sep 19, 2026
e963609
Merge remote-tracking branch 'origin/develop' into refactor/1088-sett…
OnlyReadOneBook Sep 19, 2026
8a3e8ca
maintenance(platform): dependabot PR 이 열릴 때 대표 이슈·제목·CI Test Plan 을 채…
OnlyReadOneBook Sep 19, 2026
d508497
Merge pull request #2113 from Afternote/maintenance/2112-dependabot-p…
OnlyReadOneBook Sep 19, 2026
d4b1f76
Merge pull request #2008 from Afternote/fix/1488-keypad-typography
OnlyReadOneBook Sep 19, 2026
1688d36
Merge pull request #2060 from Afternote/docs/1865-version-code-policy
OnlyReadOneBook Sep 19, 2026
31b3015
Merge pull request #2015 from Afternote/refactor/1396-setting-radio-g…
OnlyReadOneBook Sep 19, 2026
472ce0f
Merge pull request #2011 from Afternote/refactor/1901-memorial-video-…
OnlyReadOneBook Sep 19, 2026
65eae8a
Merge pull request #2010 from Afternote/fix/1861-icon-tint-token
OnlyReadOneBook Sep 19, 2026
9e75e65
Merge pull request #2009 from Afternote/refactor/1782-profile-image-size
OnlyReadOneBook Sep 19, 2026
6bbb74a
Merge pull request #2006 from Afternote/refactor/1887-remove-ui-text-…
OnlyReadOneBook Sep 19, 2026
82f4a91
Merge pull request #2005 from Afternote/refactor/1064-setting-unused
OnlyReadOneBook Sep 19, 2026
49fd5ca
Merge pull request #1991 from Afternote/fix/1891-inset-ownership
OnlyReadOneBook Sep 19, 2026
8549b52
Merge pull request #1990 from Afternote/refactor/1989-version-code-int
OnlyReadOneBook Sep 19, 2026
62c6546
Merge pull request #2106 from Afternote/dependabot/github_actions/dev…
OnlyReadOneBook Sep 19, 2026
50c560e
chore(release): Firebase 배포에 대역 안 versionCode 를 주입하고 Play 대역 하한을 적용한다
OnlyReadOneBook Sep 13, 2026
8c31d54
Merge pull request #2019 from Afternote/fix/1057-receiver-index
OnlyReadOneBook Sep 19, 2026
3a9f99f
refactor(core): 미사용 단품 라디오 API 제거 (#649)
OnlyReadOneBook Sep 13, 2026
7c13c7a
Merge remote-tracking branch 'origin/develop' into refactor/1999-navi…
OnlyReadOneBook Sep 19, 2026
9a5abd4
Merge remote-tracking branch 'origin/develop' into refactor/1992-sett…
OnlyReadOneBook Sep 19, 2026
cc241b0
Merge pull request #2001 from Afternote/refactor/1999-navigation-call…
OnlyReadOneBook Sep 19, 2026
8e66139
Merge pull request #2046 from Afternote/refactor/649-remove-legacy-radio
OnlyReadOneBook Sep 19, 2026
f6d22dd
Merge remote-tracking branch 'origin/develop' into fix/2063-plus-badg…
OnlyReadOneBook Sep 19, 2026
4c2ee09
Merge remote-tracking branch 'origin/develop' into refactor/1992-sett…
OnlyReadOneBook Sep 19, 2026
bd5b771
Merge remote-tracking branch 'origin/refactor/1992-setting-previews' …
OnlyReadOneBook Sep 19, 2026
a07bdd9
Merge remote-tracking branch 'origin/fix/2063-plus-badge-color-token'…
OnlyReadOneBook Sep 19, 2026
3c42a76
Merge remote-tracking branch 'origin/develop' into refactor/1088-sett…
OnlyReadOneBook Sep 19, 2026
b334339
test(setting): RadioGroupTest 를 이동한 RadioGroup 패키지로 옮긴다 (#1088)
OnlyReadOneBook Sep 19, 2026
1319493
test: update screenshot baselines in CI
github-actions[bot] Sep 19, 2026
d990bdc
Merge pull request #1993 from Afternote/refactor/1992-setting-previews
OnlyReadOneBook Sep 19, 2026
670f099
Merge pull request #2002 from Afternote/fix/2000-setting-menu-feedback
OnlyReadOneBook Sep 19, 2026
8cd2e26
Merge remote-tracking branch 'origin/develop' into refactor/1088-sett…
OnlyReadOneBook Sep 19, 2026
8ccfc9e
Merge remote-tracking branch 'origin/fix/2000-setting-menu-feedback' …
OnlyReadOneBook Sep 19, 2026
e5f364a
Merge remote-tracking branch 'origin/develop' into docs/1810-mvi-navi…
OnlyReadOneBook Sep 19, 2026
7981646
Merge remote-tracking branch 'origin/develop' into fix/1617-dirty-fie…
OnlyReadOneBook Sep 19, 2026
c7bdf5f
Merge pull request #2073 from Afternote/chore/2062-version-code-bands
OnlyReadOneBook Sep 19, 2026
e3b4332
fix(setting): connect profile support shortcut feedback (#551)
OnlyReadOneBook Sep 13, 2026
8a5f5b3
Merge remote-tracking branch 'origin/develop' into fix/2063-plus-badg…
OnlyReadOneBook Sep 19, 2026
33df769
Merge remote-tracking branch 'origin/develop' into refactor/1088-sett…
OnlyReadOneBook Sep 19, 2026
4811e5a
Merge pull request #2072 from Afternote/fix/2063-plus-badge-color-token
OnlyReadOneBook Sep 19, 2026
90008f2
Merge pull request #2053 from Afternote/refactor/1088-setting-feature…
OnlyReadOneBook Sep 19, 2026
26fa97d
Merge remote-tracking branch 'origin/develop' into refactor/1077-sett…
OnlyReadOneBook Sep 19, 2026
f69332d
Merge pull request #2055 from Afternote/refactor/1077-setting-resourc…
OnlyReadOneBook Sep 19, 2026
7db91c8
refactor(afternote): EditableMemorialVideo 를 세 상태로 줄이고 저장 동작이 읽히는 이름으…
OnlyReadOneBook Sep 19, 2026
54e6d12
refactor(afternote): 임시저장 프리필 계약의 이름과 매퍼 모양을 정리한다 (#2115)
OnlyReadOneBook Sep 19, 2026
a2dd618
Merge remote-tracking branch 'origin/develop' into HEAD
OnlyReadOneBook Sep 20, 2026
cd0c8aa
refactor: 토큰 재발급 단일 실행 진입점 명명 (#2107)
OnlyReadOneBook Sep 20, 2026
2c7295c
fix(setting): 수신자 목록 응답 계약 정합성 복원 (#2105)
OnlyReadOneBook Sep 20, 2026
5202414
merge: 최신 설정 패키지에 글꼴 확대 baseline 연결 (#1147)
OnlyReadOneBook Sep 20, 2026
c3af731
merge: 설정 바로가기의 최신 패키지와 리소스 이름 반영 (#551)
OnlyReadOneBook Sep 20, 2026
c757588
test: 복원 프리필 회귀 검증의 현재 스냅샷 키 사용 (#1617)
OnlyReadOneBook Sep 20, 2026
aa1d169
Merge develop into password change destination
OnlyReadOneBook Sep 20, 2026
3d73f21
refactor(setting): 설정 전용 저장소와 좁은 주입 계약 분리 (#1429)
OnlyReadOneBook Sep 20, 2026
37670dc
docs(setting): Java 테스트 모듈 참조를 코드 스팬으로 정리 (#1429)
OnlyReadOneBook Sep 20, 2026
fc5daf3
fix(ci): distinguish reusable workflows in SHA policy audit (#2126)
OnlyReadOneBook Sep 20, 2026
ed0cd5b
fix(build): raise Bouncy Castle security floor to 1.85 (#2132)
OnlyReadOneBook Sep 20, 2026
1195f35
refactor(core): 기존 ArrowIcon에 동일 렌더링을 위임한다 (#635)
OnlyReadOneBook Sep 21, 2026
9de413c
test(setting): verify greeting touch target through app UI (#2035)
OnlyReadOneBook Sep 21, 2026
2968378
chore(deps): bump the github-actions-updates group with 4 updates
dependabot[bot] Sep 21, 2026
366d3d9
docs(qa): 3차 QA 에뮬레이터 패스를 증거 대장에 남긴다
OnlyReadOneBook Sep 23, 2026
082fcc3
docs(qa): 패스키·마음의 기록 쓰기 패스를 #2120 기록에 합친다
OnlyReadOneBook Sep 23, 2026
3602ddd
docs(qa): 3차 QA 실기기 패스를 증거 대장에 남긴다
OnlyReadOneBook Sep 23, 2026
8c4f791
docs(qa): release(minify) 에뮬 스모크를 #2120 기록에 합친다
OnlyReadOneBook Sep 23, 2026
332b635
fix(core): 가로로 긴 프로필 사진이 원을 꽉 채우도록 Crop 으로 그린다 (#2143)
OnlyReadOneBook Sep 23, 2026
38e2b38
fix(core): 로그인한 기기에만 데일리 알림을 예약한다 (#2146)
OnlyReadOneBook Sep 23, 2026
e38dfbe
test: update screenshot baselines in CI
github-actions[bot] Sep 23, 2026
00be78a
fix(core,setting): predictive back 중 줄어든 앞 화면에 불투명한 바탕을 깐다 (#2145)
OnlyReadOneBook Sep 23, 2026
64cb56a
test(platform): selector 메서드가 다른 class 본문에 있으면 거절해야 한다는 정책 테스트를 먼저 둔다…
OnlyReadOneBook Sep 23, 2026
8ce61fc
fix(platform): CI Test Plan selector 의 @Test 메서드가 선언한 class 본문 안에 있는지…
OnlyReadOneBook Sep 23, 2026
691c360
fix(ci): GMD 설정 단계 429 실패를 인프라로 분류하고 Gradle 종료 코드를 보존한다 (#2157)
OnlyReadOneBook Sep 23, 2026
71d0e2a
fix(platform): selector 소속 판정의 예전보다 나빠지는 입력을 없앤다 (#2156)
OnlyReadOneBook Sep 23, 2026
098fb98
fix(core): 수신자 상세 응답 계약을 맞춰 수정 화면 조회 실패를 막는다 (#2155)
OnlyReadOneBook Sep 23, 2026
c49167f
test(core): 동시 401 5건에서 재발급이 디스패처 대기열에 갇히는 교착을 재현한다 (#2160)
OnlyReadOneBook Sep 23, 2026
0566ff5
fix(ci): 실패한 selector 재실행 뒤 1차 결과가 두 번 집계되지 않게 한다 (#2157)
OnlyReadOneBook Sep 23, 2026
f9c1437
fix(core): 재발급 클라이언트에 전용 Dispatcher 를 줘 동시 401 교착을 없앤다 (#2160)
OnlyReadOneBook Sep 23, 2026
63d9b9c
Merge pull request #2096 from Afternote/fix/2032-sender-message-date-…
Sadturtleman Sep 25, 2026
79bd01d
Merge pull request #2101 from Afternote/fix/1864-find-id-code-job-guard
Sadturtleman Sep 25, 2026
0b54ecb
Merge pull request #2097 from Afternote/fix/2027-published-diary-over…
Sadturtleman Sep 25, 2026
5d3788c
Merge pull request #2102 from Afternote/fix/2025-stale-email-verifica…
Sadturtleman Sep 25, 2026
46376ad
Merge pull request #2098 from Afternote/fix/2028-daily-question-edit-…
Sadturtleman Sep 25, 2026
05542b7
Merge pull request #2103 from Afternote/fix/2026-account-created-cred…
Sadturtleman Sep 25, 2026
4d89fcd
Merge pull request #2104 from Afternote/refactor/1851-onboarding-emai…
Sadturtleman Sep 25, 2026
02c7d51
Merge pull request #2099 from Afternote/fix/2029-concurrent-attachmen…
Sadturtleman Sep 25, 2026
699b34f
Merge pull request #2100 from Afternote/fix/2031-late-prefill-overwrite
Sadturtleman Sep 25, 2026
9b7e19d
refactor(afternote): 수정 입력 모델 이름을 Input으로 정리 (#1617)
OnlyReadOneBook Sep 25, 2026
973ba02
Merge pull request #2161 from Afternote/fix/2157-gmd-dependency-429-r…
OnlyReadOneBook Sep 25, 2026
71a5d68
Merge pull request #2158 from Afternote/fix/2156-selector-class-scope
OnlyReadOneBook Sep 25, 2026
fc5a067
Merge pull request #2134 from Afternote/refactor/635-right-arrow-dele…
OnlyReadOneBook Sep 25, 2026
11b87b4
Merge pull request #2129 from Afternote/fix/2126-reusable-workflow-audit
OnlyReadOneBook Sep 25, 2026
3aa2856
refactor(afternote): 마지막 말씀 DTO 변환 목적을 함수명에 명시 (#1617)
OnlyReadOneBook Sep 25, 2026
58bdf0f
refactor(afternote): 수신자 참조 입력 모델 이름 정리 (#1617)
OnlyReadOneBook Sep 25, 2026
78f7f90
fix(afternote): 기준 스냅샷 오류 문구 명확화 (#1617)
OnlyReadOneBook Sep 25, 2026
32a5a6d
refactor(afternote): 비교 스냅샷을 카테고리별로 분리 (#2163)
OnlyReadOneBook Sep 25, 2026
6ae7539
refactor(afternote): 수정 입력의 수신자를 id 목록으로 받고 wire 포장은 data 에서 끝낸다 (#1617)
OnlyReadOneBook Sep 25, 2026
11d6459
fix(afternote): 요청 매퍼의 파일 안 toDto 헬퍼를 private 으로 줄인다 (#1617)
OnlyReadOneBook Sep 25, 2026
68e08a1
refactor(afternote): 수정 입력의 수신자 id 계약 통합 (#2163)
OnlyReadOneBook Sep 25, 2026
bd12e59
refactor(afternote): 수정 페이로드의 미디어 URL 인자 이름을 타입과 맞춘다 (#1617)
OnlyReadOneBook Sep 25, 2026
e4bb3d2
refactor(afternote): 미디어 URL 인자 이름 통합 (#2163)
OnlyReadOneBook Sep 25, 2026
70cbf38
Merge pull request #1626 from Afternote/fix/1617-dirty-field-patch
OnlyReadOneBook Sep 25, 2026
e6441b8
Merge pull request #2012 from Afternote/security/1876-backup-rules
OnlyReadOneBook Sep 25, 2026
522c8c3
refactor(core): 목록이 주지 않는 Receiver.authCode 를 모델에서 뺀다 (#2105)
OnlyReadOneBook Sep 25, 2026
e1cc5f0
Merge pull request #2120 from Afternote/fix/2105-receiver-list-response
OnlyReadOneBook Sep 26, 2026
b0fe643
Merge pull request #2118 from Afternote/refactor/2107-reissue-once
OnlyReadOneBook Sep 26, 2026
f3cc6c1
fix(core): refresh active receiver lists after edits (#2127)
OnlyReadOneBook Sep 20, 2026
2f86b9c
fix(core): 수신자 목록 조회의 로딩·실패를 상태 Flow 로 보존한다 (#2045)
OnlyReadOneBook Sep 23, 2026
d71279c
fix(setting): 수신자 목록의 조회 중·실패를 0건 안내와 구분하고 다시 시도를 잇는다 (#1281)
OnlyReadOneBook Sep 23, 2026
8ac6033
fix(core): scope receiver cache to persisted login sessions (#2135)
OnlyReadOneBook Sep 21, 2026
f469f54
test: update screenshot baselines in CI
github-actions[bot] Sep 23, 2026
9134baf
test(core): preserve receiver update coverage on stacked base (#2135)
OnlyReadOneBook Sep 21, 2026
d01c6d5
fix(setting): 다시 구독한 첫 조회가 실패해도 보이던 수신자 행을 남긴다 (#2045)
OnlyReadOneBook Sep 23, 2026
1477af2
Merge pull request #2133 from Afternote/fix/2132-bouncycastle-securit…
OnlyReadOneBook Sep 26, 2026
bb7fd29
Merge remote-tracking branch 'origin/develop' into refactor/2114-memo…
OnlyReadOneBook Sep 26, 2026
d154344
Merge pull request #2136 from Afternote/test/2035-setting-touch-contract
OnlyReadOneBook Sep 26, 2026
21e9e03
test(afternote): 프로세스 사망 복원 테스트의 스냅샷 키를 v6 로 맞춘다 (#2114)
OnlyReadOneBook Sep 26, 2026
4766777
Merge pull request #2148 from Afternote/fix/2143-profile-image-crop
OnlyReadOneBook Sep 26, 2026
0073482
Merge pull request #2116 from Afternote/refactor/2114-memorial-video-…
OnlyReadOneBook Sep 26, 2026
55b7a2f
Merge branch 'origin/fix/2083-password-change-destination' into refac…
OnlyReadOneBook Sep 26, 2026
f2e7429
Merge branch 'origin/fix/2145-predictive-back-opaque-entry' into refa…
OnlyReadOneBook Sep 26, 2026
dbd7145
Merge branch 'origin/fix/2045-receiver-list-load-state' into refactor…
OnlyReadOneBook Sep 26, 2026
75f81c3
test(app): 발신자 카드에서 상세로 들어가는 실제 Hilt 경로를 androidTest 로 연다 (#2168)
OnlyReadOneBook Sep 26, 2026
f985d45
fix(receiver): 발신자 상세 VM 이 route 를 assisted 로 받아 진입 크래시를 없앤다 (#2168)
OnlyReadOneBook Sep 26, 2026
e2b6ee4
Merge pull request #2141 from Afternote/docs/2140-qa-emulator-evidence
OnlyReadOneBook Sep 26, 2026
4f21b38
test(core): 목록 모델에서 빠진 Receiver.authCode 인자를 테스트에서 걷어낸다 (#2127)
OnlyReadOneBook Sep 26, 2026
fbf1bff
test(core): 목록 모델에서 빠진 Receiver.authCode 인자를 테스트에서 걷어낸다 (#2135)
OnlyReadOneBook Sep 26, 2026
cef12aa
test(core,setting): 목록 모델에서 빠진 Receiver.authCode 인자를 테스트에서 걷어낸다 (#2045)
OnlyReadOneBook Sep 26, 2026
08d1813
test(setting): 목록 모델에서 빠진 Receiver.authCode 인자를 테스트에서 걷어낸다 (#2045)
OnlyReadOneBook Sep 26, 2026
fe4d51a
docs(afternote,receiver): Nav3 이관 뒤 코드와 어긋난 KDoc·주석을 고친다 (#2170)
OnlyReadOneBook Sep 26, 2026
52aa93a
test(receiver): 흐름 VM 테스트에서 사라진 Robolectric 사유와 러너를 뺀다 (#2170)
OnlyReadOneBook Sep 26, 2026
bf2c211
refactor(setting): 설정 흐름을 Navigation 3 로컬 스택으로 이관한다 (#1695)
OnlyReadOneBook Sep 26, 2026
147983d
refactor(app): 설정을 루트에 host destination 한 칸으로 등록한다 (#1695)
OnlyReadOneBook Sep 26, 2026
3a03271
test(setting): 설정 로컬 백스택의 back 체인·외부 경계·키 직렬화를 고정한다 (#1695)
OnlyReadOneBook Sep 26, 2026
0f8b88f
test(konsist): 설정 등록부가 사라진 뒤 바탕 가드 문구와 QA 절차를 맞춘다 (#1695)
OnlyReadOneBook Sep 26, 2026
7227eae
test(app,setting): 홈 수신인 칩의 등록 화면 시작점을 인자와 첫 화면에서 잰다 (#1695)
OnlyReadOneBook Sep 26, 2026
9738421
Merge branch 'origin/fix/2045-receiver-list-load-state' into refactor…
OnlyReadOneBook Sep 26, 2026
92d29da
test(app): 루트가 Route.Setting 인자를 설정 host 에 넘기는 결선을 androidTest 로 잰다 (…
OnlyReadOneBook Sep 26, 2026
62533ee
Merge pull request #2162 from Afternote/fix/2160-reissue-dispatcher-d…
OnlyReadOneBook Sep 26, 2026
1d88bce
build(app): app 이 직접 쓰지 않는 feature:afternote:domain 의존을 빼고 Nav2 회귀 주석…
OnlyReadOneBook Sep 26, 2026
cfd7352
Merge remote-tracking branch 'origin/develop' into refactor/2115-draf…
OnlyReadOneBook Sep 26, 2026
e309af9
Merge remote-tracking branch 'origin/develop' into refactor/1429-sett…
OnlyReadOneBook Sep 26, 2026
c627462
Merge pull request #2171 from Afternote/docs/2170-nav3-stale-kdoc
OnlyReadOneBook Sep 27, 2026
117e125
test(app): 발신자 상세 진입 테스트의 IME와 카드 선택을 동기화 (#2168)
OnlyReadOneBook Sep 27, 2026
e03ae17
Merge pull request #2004 from Afternote/fix/1147-withdraw-font-scale
OnlyReadOneBook Sep 27, 2026
4dfea2d
Merge pull request #2033 from Afternote/refactor/1809-notification-mvi
OnlyReadOneBook Sep 27, 2026
3ed5409
Merge pull request #2038 from Afternote/docs/1810-mvi-navigation-boun…
OnlyReadOneBook Sep 27, 2026
6e7e08a
Merge pull request #2049 from Afternote/fix/551-profile-shortcut-feed…
OnlyReadOneBook Sep 27, 2026
d40e4ac
refactor(setting): Nav3 선행에서 후속 기능 구현을 분리한다 (#1695)
OnlyReadOneBook Sep 27, 2026
7f692f7
Merge remote-tracking branch 'origin/develop' into refactor/1429-sett…
OnlyReadOneBook Sep 27, 2026
92bd161
refactor(setting): 좁은 저장소 계약 위에 Nav3 생성 경계를 연결한다 (#1695)
OnlyReadOneBook Sep 27, 2026
bd0b84a
Merge develop into draft-prefill mapper before editor stack integrati…
OnlyReadOneBook Sep 27, 2026
fdaa5df
Merge develop before category snapshot stack integration (#2163)
OnlyReadOneBook Sep 27, 2026
8093a1c
refactor(setting): Nav3 목록 진입을 최종 MVI 관찰 계약에 연결한다 (#1805)
OnlyReadOneBook Sep 27, 2026
cd2ac5d
fix(core,app): Nav3 entry 배경을 불투명하게 유지한다 (#2145)
OnlyReadOneBook Sep 27, 2026
f86ae41
style: normalize setting Nav3 app imports
OnlyReadOneBook Sep 27, 2026
84c3cb6
refactor: keep setting route consumers within presentation
OnlyReadOneBook Sep 27, 2026
40cae1d
fix: connect password change after setting Nav3 foundation
OnlyReadOneBook Sep 27, 2026
8525b9a
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
b23b87f
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
ceba816
Merge remote-tracking branch 'origin/fix/2135-receiver-session-cache'…
OnlyReadOneBook Sep 27, 2026
8813e31
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
2f069cf
Merge latest develop and adapt setting shortcut test repositories
OnlyReadOneBook Sep 27, 2026
d6d3350
fix(core,setting): Nav3 목록 조회 상태를 MVI 재시도로 연결한다 (#2045)
OnlyReadOneBook Sep 27, 2026
aa64d28
Merge remote-tracking branch 'origin/refactor/1429-setting-repositori…
OnlyReadOneBook Sep 27, 2026
6fc07e9
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
94be55e
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
3912499
Merge remote-tracking branch 'origin/refactor/1695-setting-nav3' into…
OnlyReadOneBook Sep 27, 2026
a7634f4
Merge pull request #2123 from Afternote/refactor/1429-setting-reposit…
OnlyReadOneBook Sep 27, 2026
6493593
Merge pull request #2130 from Afternote/fix/2127-receiver-update-refresh
OnlyReadOneBook Sep 27, 2026
9c97fde
Merge pull request #2151 from Afternote/fix/2146-daily-notification-s…
OnlyReadOneBook Sep 27, 2026
6cb83f6
fix(core): remove obsolete receiver detail authCode (#2155)
OnlyReadOneBook Sep 27, 2026
1d4c797
Merge remote-tracking branch 'origin/develop' into HEAD
OnlyReadOneBook Sep 27, 2026
4426b6f
fix(core): integrate current develop session repository contract
OnlyReadOneBook Sep 27, 2026
cd9b78e
test(app): 제거된 수신자 인증 코드 인자를 정리한다 (#2155)
OnlyReadOneBook Sep 27, 2026
19a0bd6
Merge pull request #2169 from Afternote/fix/2168-sender-detail-route
OnlyReadOneBook Sep 27, 2026
2046aba
Merge pull request #2176 from Afternote/build/2172-app-stale-domain-dep
OnlyReadOneBook Sep 27, 2026
0c5748d
Merge pull request #2159 from Afternote/fix/2155-receiver-detail-resp…
OnlyReadOneBook Sep 27, 2026
35a03ee
fix(ci): generate dependency graphs for source-only PRs (#2185)
OnlyReadOneBook Sep 27, 2026
ea8f89a
Merge pull request #2173 from Afternote/refactor/1695-setting-nav3
OnlyReadOneBook Sep 27, 2026
c7224a0
Merge pull request #2153 from Afternote/fix/2145-predictive-back-opaq…
OnlyReadOneBook Sep 27, 2026
97f4fee
Merge pull request #2094 from Afternote/fix/2083-password-change-dest…
OnlyReadOneBook Sep 27, 2026
b332656
refactor(core,setting,afternote): 수신자 목록 조회 실패 안내와 갱신 실패 배너를 core:ui …
OnlyReadOneBook Sep 27, 2026
390d984
Merge pull request #2137 from Afternote/fix/2135-receiver-session-cache
OnlyReadOneBook Sep 27, 2026
a2016aa
Merge pull request #2057 from Afternote/fix/939-receiver-render-index
OnlyReadOneBook Sep 28, 2026
842a896
refactor(afternote): 응답 playlist 본문을 memorial 로 부르고 null 조건 주석을 BE 기준…
OnlyReadOneBook Sep 28, 2026
7d49a40
Merge pull request #2117 from Afternote/refactor/2115-draft-prefill-m…
OnlyReadOneBook Sep 28, 2026
65fce8e
Merge pull request #2164 from Afternote/refactor/2163-category-snapshot
OnlyReadOneBook Sep 28, 2026
43d600e
Merge remote-tracking branch 'origin/develop' into tmp/2154-conflict
OnlyReadOneBook Sep 28, 2026
012f7eb
Merge pull request #2154 from Afternote/fix/2045-receiver-list-load-s…
OnlyReadOneBook Sep 28, 2026
7e8209f
Merge pull request #2138 from Afternote/dependabot/github_actions/dev…
OnlyReadOneBook Sep 28, 2026
4c9c806
fix(ci): CI 파서의 정규식 처리 지연과 XML 이중 해제 수정 (#2218)
OnlyReadOneBook Sep 30, 2026
3c1f642
Merge pull request #2221 from Afternote/fix/2218-codeql-parser-security
OnlyReadOneBook Oct 1, 2026
756e456
Merge pull request #2186 from Afternote/fix/2185-stack-parent-depende…
OnlyReadOneBook Oct 1, 2026
fad4615
ci(platform): 댓글 없는 QA 배포 시점 판정 (#2239)
OnlyReadOneBook Oct 2, 2026
8db2d75
Merge pull request #2240 from Afternote/chore/2239-qa-distribution-de…
OnlyReadOneBook Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ body:
- timeletter — 타임레터
- mindrecord — 마음의 기록
- home — 홈
- platform — Android 앱·CI·빌드·릴리스·저장소 운영
- app — 앱 셸·루트 네비게이션·앱 모듈 공통
- platform — CI·빌드·릴리스·저장소 운영
validations:
required: true

Expand Down
35 changes: 2 additions & 33 deletions .github/ci-expected-failures.json
Original file line number Diff line number Diff line change
@@ -1,37 +1,6 @@
{
"schemaVersion": 1,
"unitTests": [
{
"task": ":feature:timeletter:data:testDebugUnitTest",
"className": "com.afternote.feature.timeletter.data.dto.TimeLetterDtoContractTest",
"tests": [
"발신 응답의 명시적 null과 빈 배열은 정상 파싱된다",
"발신 응답에는 존재하지 않는 deliveredAt 없이 정상 파싱된다",
"수신 응답의 기본값 제거 대상 키가 빠지면 실패한다",
"수신 응답의 조건부 null과 공개 전 빈 blocks는 정상 파싱된다"
],
"issues": [
790,
873
],
"reason": "타임레터 DTO 누락 키 계약 게이트 — 구현 머지 전까지 의도된 실패"
}
],
"unitTests": [],
"androidTests": [],
"screenshotModules": [
{
"module": ":feature:setting:presentation",
"issues": [
1360
],
"reason": "설정 화면 screenshotTest용 Content 경계 분리 대기 — compileDebugScreenshotTestKotlin 실패"
},
{
"module": ":feature:timeletter:presentation",
"issues": [
1361
],
"reason": "목록 화면 screenshotTest용 Content 경계 분리 대기 — compileDebugScreenshotTestKotlin 실패"
}
]
"screenshotModules": []
}
59 changes: 40 additions & 19 deletions .github/scripts/audit-org-action-pinning.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/usr/bin/env node

// 조직(orgs/<org>) 하위 전 저장소의 워크플로·composite action 이 쓰는 `uses:` 를
// 전수로 모아 floating(태그·브랜치) 참조와 40자리 SHA 고정 참조로 가른다.
// 전수로 모아 floating 액션, 40자리 SHA 고정 액션, 재사용 워크플로로 가른다.
//
// `orgs/<org>/actions/permissions` 의 `sha_pinning_required` 를 켜면 조직 하위
// 저장소 전부에 즉시 적용된다. floating 참조가 하나라도 남아 있으면 그 저장소의
// 저장소 전부에 즉시 적용된다. floating 액션이 하나라도 남아 있으면 그 저장소의
// run 은 job 이 만들어지기 전에 `startup_failure` 로 죽고 로그에 사유가 남지 않는다.
// 그래서 켜기 전에 이 감사를 돌려 0건인지 확인한다.
// 그래서 켜기 전에 이 감사를 돌려 0건인지 확인한다. 원격 재사용 워크플로는
// 이 SHA 강제 정책의 예외이며 태그 참조도 허용된다.
//
// 사용법:
// GH_TOKEN=$(gh auth token) node .github/scripts/audit-org-action-pinning.mjs \
Expand All @@ -26,27 +27,39 @@ const PAGE_SIZE = 100;

const WORKFLOW_PATH = /^\.github\/workflows\/[^/]+\.ya?ml$/;
const ACTION_MANIFEST_PATH = /(?:^|\/)action\.ya?ml$/;
const REMOTE_REUSABLE_WORKFLOW = /^[^/\s@]+\/[^/\s@]+\/\.github\/workflows\/[^/\s@]+\.ya?ml$/;

/**
* 워크플로·action 매니페스트 원문에서 `uses:` 값을 순서대로 뽑는다.
* 워크플로·action 매니페스트 원문에서 `uses:` 값과 호출 위치를 순서대로 뽑는다.
*
* YAML 파서를 쓰지 않는 이유는 `uses:` 가 step 시퀀스·job 레벨(reusable workflow)
* 양쪽에 나타나고, 주석 처리된 줄은 정책 대상이 아니기 때문이다. 줄 단위로 보는
* 편이 정책이 보는 범위와 정확히 겹친다.
* 양쪽에 나타나기 때문이다. 들여쓰기의 mapping 경로로 jobs.<id>.uses만 구분하고,
* step이나 composite action의 같은 경로 문자열에는 워크플로 예외를 적용하지 않는다.
*/
export function extractActionReferences(source) {
export function extractActionReferences(source, sourcePath = "") {
const references = [];
const parents = [];
for (const line of String(source ?? "").split("\n")) {
if (/^\s*#/.test(line)) {
if (/^\s*(?:#.*)?$/.test(line)) {
continue;
}
const indent = line.search(/\S/);
while (parents.length > 0 && parents.at(-1).indent >= indent) {
parents.pop();
}
const match = /^\s*(?:-\s+)?uses:\s*(.+?)\s*$/.exec(line);
if (!match) {
continue;
if (match) {
const reference = stripInlineComment(match[1]);
const reusableWorkflow = WORKFLOW_PATH.test(sourcePath) &&
!line.trimStart().startsWith("-") && parents.length === 2 &&
parents[0].key === "jobs" && parents[0].indent === 0;
if (reference.length > 0) {
references.push({ reference, reusableWorkflow });
}
}
const value = stripInlineComment(match[1]);
if (value.length > 0) {
references.push(value);
const mapping = /^\s*(?:([A-Za-z0-9_-]+)|["']([A-Za-z0-9_-]+)["'])\s*:/.exec(line);
if (mapping) {
parents.push({ indent, key: mapping[1] ?? mapping[2] });
}
}
return references;
Expand All @@ -72,10 +85,11 @@ function stripInlineComment(value) {
* SHA 고정 정책의 대상이 아니다.
* - `docker`: `docker://` 참조. 액션 레지스트리가 아니라 이미지라 대상이 아니다.
* - `expression`: `${{ }}` 가 섞인 참조. 정적으로 판정할 수 없으니 사람이 본다.
* - `reusable-workflow`: 버전이 있는 원격 재사용 워크플로. SHA 강제 정책의 예외다.
* - `pinned`: `@` 뒤가 40자리 소문자 hex.
* - `floating`: 그 밖(태그 `@v4`·브랜치 `@main`·짧은 SHA). 정책을 켜면 막힌다.
*/
export function classifyActionReference(reference) {
export function classifyActionReference(reference, { reusableWorkflow = false } = {}) {
const value = String(reference ?? "").trim();
if (value.length === 0) {
return { reference: value, kind: "empty", action: null, version: null };
Expand All @@ -95,6 +109,9 @@ export function classifyActionReference(reference) {
}
const action = value.slice(0, separator);
const version = value.slice(separator + 1);
if (reusableWorkflow && version.length > 0 && REMOTE_REUSABLE_WORKFLOW.test(action)) {
return { reference: value, kind: "reusable-workflow", action, version };
}
const kind = /^[0-9a-f]{40}$/.test(version) ? "pinned" : "floating";
return { reference: value, kind, action, version };
}
Expand All @@ -108,7 +125,7 @@ export function classifyActionReference(reference) {
export function collectExternalActionNames(entries) {
const names = new Set();
for (const entry of entries) {
if (entry.kind === "pinned" || entry.kind === "floating" || entry.kind === "unversioned") {
if (["pinned", "floating", "unversioned", "reusable-workflow"].includes(entry.kind)) {
names.add(entry.action);
}
}
Expand All @@ -125,6 +142,7 @@ export function summarizeAudit(entries) {
total: 0,
pinned: 0,
floating: 0,
reusableWorkflows: 0,
local: 0,
other: 0,
floatingReferences: [],
Expand All @@ -139,6 +157,8 @@ export function summarizeAudit(entries) {
bucket.floatingReferences.push(entry);
} else if (entry.kind === "local") {
bucket.local += 1;
} else if (entry.kind === "reusable-workflow") {
bucket.reusableWorkflows += 1;
} else {
bucket.other += 1;
}
Expand All @@ -152,6 +172,7 @@ export function summarizeAudit(entries) {
references: entries.length,
pinned: repositories.reduce((sum, item) => sum + item.pinned, 0),
floating: repositories.reduce((sum, item) => sum + item.floating, 0),
reusableWorkflows: repositories.reduce((sum, item) => sum + item.reusableWorkflows, 0),
local: repositories.reduce((sum, item) => sum + item.local, 0),
other: repositories.reduce((sum, item) => sum + item.other, 0),
},
Expand Down Expand Up @@ -259,13 +280,13 @@ async function scanRevision(apiUrl, repository, revision, label, token, blobCach
await requestText(`${apiUrl}/repos/${repository}/git/blobs/${blob.sha}`, token),
);
}
for (const reference of extractActionReferences(blobCache.get(cacheKey))) {
for (const { reference, reusableWorkflow } of extractActionReferences(blobCache.get(cacheKey), blob.path)) {
entries.push({
repository,
revision,
revisionLabel: label,
path: blob.path,
...classifyActionReference(reference),
...classifyActionReference(reference, { reusableWorkflow }),
});
}
}
Expand Down Expand Up @@ -357,10 +378,10 @@ async function main() {
console.error(
`scanned ${scannedRevisions.length} revisions across ${repositories.length} repositories: ` +
`${totals.references} uses (${totals.pinned} pinned, ${totals.floating} floating, ` +
`${totals.local} local, ${totals.other} other)`,
`${totals.reusableWorkflows} reusable workflows, ${totals.local} local, ${totals.other} other)`,
);
if (!compatible) {
console.error("floating references remain; sha_pinning_required would break these runs");
console.error("floating action references remain; sha_pinning_required would break these runs");
process.exitCode = 1;
}
}
Expand Down
82 changes: 79 additions & 3 deletions .github/scripts/audit-org-action-pinning.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ test("collects uses from step sequences, job-level reusable workflows, and quote
" - uses: ./.github/actions/setup-ci-config",
].join("\n");

assert.deepEqual(extractActionReferences(source), [
assert.deepEqual(extractActionReferences(source).map((entry) => entry.reference), [
"./.github/workflows/lint.yml",
PINNED,
"actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c",
Expand All @@ -40,7 +40,7 @@ test("ignores commented-out uses lines and run steps that merely mention uses",
` - uses: ${PINNED}`,
].join("\n");

assert.deepEqual(extractActionReferences(source), [PINNED]);
assert.deepEqual(extractActionReferences(source).map((entry) => entry.reference), [PINNED]);
});

test("separates SHA-pinned references from every floating form the policy rejects", () => {
Expand All @@ -65,6 +65,80 @@ test("exempts the reference kinds the pinning policy does not govern", () => {
assert.equal(classifyActionReference("actions/checkout").kind, "unversioned");
});

test("keeps remote reusable workflows compatible and in the allow-list for every supported ref", () => {
for (const file of ["build.yml", "build.yaml"]) {
for (const version of ["v1", "main", "release/v1", "a".repeat(40)]) {
const action = `octo-org/another-repo/.github/workflows/${file}`;
const reference = `${action}@${version}`;
const classified = classifyActionReference(reference, { reusableWorkflow: true });
const summary = summarizeAudit([{ repository: "fixture", ...classified }]);

assert.deepEqual(classified, { reference, kind: "reusable-workflow", action, version });
assert.equal(summary.compatible, true);
assert.equal(summary.totals.floating, 0);
assert.equal(summary.totals.reusableWorkflows, 1);
assert.equal(summary.repositories[0].reusableWorkflows, 1);
assert.deepEqual(summary.externalActions, [action]);
}
}
});

test("still blocks floating actions when reusable workflows appear in the same audit", () => {
const summary = summarizeAudit([
"octo-org/another-repo/.github/workflows/build.yml@v1",
"gradle/actions/setup-gradle@v6",
].map((reference) => ({ repository: "fixture", ...classifyActionReference(reference, { reusableWorkflow: true }) })));

assert.equal(summary.compatible, false);
assert.equal(summary.totals.reusableWorkflows, 1);
assert.equal(summary.totals.floating, 1);
assert.deepEqual(summary.repositories[0].floatingReferences.map((entry) => entry.reference), [
"gradle/actions/setup-gradle@v6",
]);
});

test("does not exempt malformed workflow paths or an empty version", () => {
for (const reference of [
"octo-org/another-repo/.github/workflows/build.yml@",
"octo-org/another-repo/.github/workflows/nested/build.yml@v1",
"octo-org/another-repo/.github/workflows/build.yml/action.yml@v1",
"octo-org/another-repo/.github/workflows/build.txt@v1",
"octo-org/another-repo/sub/.github/workflows/build.yml@v1",
]) {
const entry = classifyActionReference(reference, { reusableWorkflow: true });
assert.equal(entry.kind, "floating", reference);
assert.equal(summarizeAudit([{ repository: "fixture", ...entry }]).compatible, false);
}
});

test("applies the exception only at jobs.<id>.uses in workflow files", () => {
const reference = "octo-org/another-repo/.github/workflows/build.yml@main";
const source = [
"jobs:",
" reuse:",
` uses: ${reference}`,
" action:",
" steps:",
` - uses: ${reference}`,
" - name: another action",
` uses: ${reference}`,
" 'second-reuse':",
` uses: ${reference}`,
].join("\n");
const entries = extractActionReferences(source, ".github/workflows/ci.yml").map((entry) => ({
repository: "fixture", ...classifyActionReference(entry.reference, entry),
}));
assert.deepEqual(entries.map((entry) => entry.kind), [
"reusable-workflow", "floating", "floating", "reusable-workflow",
]);
assert.equal(summarizeAudit(entries).compatible, false);

const composite = extractActionReferences(`runs:\n using: composite\n steps:\n - uses: ${reference}`, "action.yml");
assert.equal(classifyActionReference(composite[0].reference, composite[0]).kind, "floating");
assert.equal(classifyActionReference(reference).kind, "floating");
assert.ok(extractActionReferences(source, "action.yml").every((entry) => !entry.reusableWorkflow));
});

test("keeps the subpath when naming an action, because allow-list wildcards stop at the slash", () => {
const reference = classifyActionReference("gradle/actions/setup-gradle@v6");
assert.equal(reference.action, "gradle/actions/setup-gradle");
Expand Down Expand Up @@ -100,7 +174,9 @@ test("summarizes per repository and reports incompatibility when any floating re

const summary = summarizeAudit(entries);
assert.equal(summary.compatible, false);
assert.deepEqual(summary.totals, { references: 3, pinned: 1, floating: 1, local: 1, other: 0 });
assert.deepEqual(summary.totals, {
references: 3, pinned: 1, floating: 1, reusableWorkflows: 0, local: 1, other: 0,
});
assert.deepEqual(
summary.repositories.map((item) => [item.repository, item.pinned, item.floating]),
[
Expand Down
50 changes: 49 additions & 1 deletion .github/scripts/awaiting-author-policy.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";

import { judgeAwaitingAuthor } from "./label-awaiting-author-prs.mjs";
import {
judgeAwaitingAuthor,
parseReviewGateExemptAuthors,
planAwaitingAuthorLabels,
} from "./label-awaiting-author-prs.mjs";

const guard = await readFile(new URL("../workflows/review-debt-guard.yml", import.meta.url), "utf8");
const reconcile = await readFile(new URL("../workflows/conflict-label.yml", import.meta.url), "utf8");
const script = await readFile(new URL("./label-awaiting-author-prs.mjs", import.meta.url), "utf8");
const authorDebtCheck = await readFile(new URL("./check-author-debt.mjs", import.meta.url), "utf8");
const exemptAuthors = parseReviewGateExemptAuthors(guard);

test("가드는 작성자 무조치를 공통 판정 CLI 로 검사한다", () => {
// 라벨은 주기 리컨사일 결과라 입장 시점에 스테일할 수 있다. 가드는 live PR 목록을 읽는
Expand All @@ -18,6 +23,49 @@ test("가드는 작성자 무조치를 공통 판정 CLI 로 검사한다", () =
assert.match(script, /export function findAuthorDebts/);
});

test("라벨 판정은 입장 가드에 선언된 작성자 면제 목록을 직접 읽는다", () => {
assert.match(guard, /^\s*REVIEW_GATE_EXEMPT_AUTHORS:/m);
assert.match(guard, /\$REVIEW_GATE_EXEMPT_AUTHORS/);
assert.match(script, /new URL\("\.\.\/workflows\/review-debt-guard\.yml", import\.meta\.url\)/);
assert.doesNotMatch(script, /review-gate-policy\.json/);
const mainAt = script.indexOf("async function main()");
assert.ok(mainAt > 0);
const main = script.slice(mainAt);
assert.match(main, /parseReviewGateExemptAuthors\(/);
assert.match(main, /planAwaitingAuthorLabels\(\{[^}]*\bexemptAuthors\b/);
});

test("workflow 파일이 없는 가드 checkout에서도 작성자 빚 판정을 import할 수 있다", async () => {
// data URL 에는 상대 workflow 경로가 없다. 모듈을 불러오는 순간 목록을 읽으면
// scripts 만 checkout 하는 오래된 가드와 마찬가지로 import가 실패한다.
const module = await import(`data:text/javascript;base64,${Buffer.from(script).toString("base64")}`);

assert.equal(typeof module.findAuthorDebts, "function");
assert.equal(typeof module.judgeAwaitingAuthor, "function");
});

test("가드의 면제 목록에 있는 작성자는 라벨 계획에서도 빠진다", () => {
const pullRequests = exemptAuthors.map((login, index) => ({
number: index + 1,
isDraft: false,
author: { login: login.toUpperCase() },
labels: { nodes: [{ name: "awaiting-author" }] },
reviews: {
nodes: [{
state: "CHANGES_REQUESTED",
submittedAt: "2026-08-29T00:00:00Z",
authorCanPushToRepository: true,
author: { login: "reviewer" },
}],
},
}));
const plan = planAwaitingAuthorLabels({ pullRequests, exemptAuthors });

assert.deepEqual(plan.toLabel, []);
assert.deepEqual(plan.toUnlabel.map((entry) => entry.number), pullRequests.map(({ number }) => number));
assert.ok(plan.toUnlabel.every(({ reason }) => reason === "리뷰 게이트 면제 작성자"));
});

test("리뷰어 빚과 작성자 빚은 한 번의 안내와 종료로 합친다", () => {
// 두 경로가 각각 댓글·close 를 수행하면 같은 opened 이벤트에서 중복 코멘트와 경합이
// 생긴다. 두 TSV 를 모두 만든 뒤 한 번만 최종 결정을 내려야 한다.
Expand Down
4 changes: 3 additions & 1 deletion .github/scripts/check-author-debt.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env node

// 새 PR 작성자가 변경요청을 받은 자기 PR 을 방치하고 있는지 live 상태로 검사한다.
// 새 PR 을 여는 사람이 변경요청을 받은 «자기가 담당하는» PR 을 방치하고 있는지 live 상태로
// 검사한다. 담당은 어사인이고 어사인이 비면 작성자다(#1974) — AUTHOR 는 여는 사람의 로그인이지
// «작성자 필터» 가 아니다.
// 라벨은 스테일할 수 있으므로 입장 판정에 사용하지 않는다. 열린 PR 을 한 번 조회한 뒤
// label-awaiting-author-prs.mjs 의 SSOT 판정을 재사용하고, 워크플로가 댓글과 close 를 한 번만
// 처리할 수 있도록 결과만 TSV 로 넘긴다.
Expand Down
Loading
Loading