From bb651741b39d46f6b84d022cab8cb1aee557af68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sun, 30 Aug 2026 12:31:57 +0900 Subject: [PATCH] =?UTF-8?q?refactor(receiver):=20=EC=88=98=EC=8B=A0?= =?UTF-8?q?=EC=9E=90=20=EA=B4=80=EC=A0=90=20=EB=A7=88=EC=8A=A4=ED=84=B0=20?= =?UTF-8?q?=ED=82=A4=20=EC=9D=B4=EB=A6=84=EC=9D=84=20masterKey=20=EB=A1=9C?= =?UTF-8?q?=20=EB=AA=A8=EC=9D=80=EB=8B=A4=20(#1554)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 같은 UUID 를 층마다 다르게 불렀다 — 사용자에게는 «마스터 키», 코드에서는 authCode·accessCode, 화면 클래스는 MasterKey*. 한 시그니처에 둘이 함께 나오기도 했다(verifyMasterKey(authCode:), it.accessCode == authCode). 이름이 갈린 뿌리는 서버다. 같은 값을 /users/receivers 는 authCode 로, record-boxes 는 accessCode 로, 헤더는 X-Auth-Code 로 부른다(0830 실측). 서버가 이름을 바꾸는 건 깨지는 변경이라, FE 가 DTO 경계에서 흡수하고 안쪽은 제품 용어 하나로 간다. - DTO 프로퍼티와 @SerialName 은 서버 필드명 그대로 유지 - 도메인·저장소·화면·테스트는 masterKey 로 통일 - ReceiverAuthCodeDataSource/DataStore → ReceiverMasterKey* **이메일 인증번호는 대상이 아니다.** verifyEmailAuthCode 의 authCode 는 이메일로 오는 6자리라 마스터 키와 다른 값이다. 일괄 치환이 한 번 이것까지 바꿔 컴파일이 깨졌고, 되돌렸다. 저장 계약은 건드리지 않았다 — DataStore 파일명 afternote_receiver_auth, Preferences 키 receiver_auth_code, 헤더 X-Auth-Code 전부 그대로다. 상수명만 MASTER_KEY 로 바뀌고 값은 유지되므로 기존 저장값을 계속 읽는다. --- .../ReceiverAdvancedAndroidTest.kt | 8 +-- .../navigation/AppNavigationActions.kt | 2 +- ...Store.kt => ReceiverMasterKeyDataStore.kt} | 2 +- ...kt => ReceiverMasterKeyDataStoreModule.kt} | 6 +- .../receiver/data/dto/ReceiverAuthDto.kt | 6 +- ...urce.kt => ReceiverMasterKeyDataSource.kt} | 16 ++--- .../data/network/ReceiverAuthInterceptor.kt | 8 +-- .../IdentityVerificationRepositoryImpl.kt | 2 +- .../ReceiverAuthRepositoryImpl.kt | 4 +- .../repositoryimpl/ReceiverRepositoryImpl.kt | 14 ++--- .../data/dto/ReceivedRecordBoxContractTest.kt | 4 +- .../data/dto/ReceiverEmailAuthContractTest.kt | 8 +-- .../domain/model/ReceiverAuthModels.kt | 6 +- .../repository/ReceiverAuthRepository.kt | 8 +-- ...eceiverDeliveryDocumentUploadRepository.kt | 2 +- .../domain/repository/ReceiverRepository.kt | 6 +- .../testing/FakeReceiverRepositoriesTest.kt | 32 +++++----- .../testing/FakeReceiverAuthRepository.kt | 6 +- .../domain/testing/FakeReceiverRepository.kt | 60 +++++++++---------- .../DeliveryVerificationFlowViewModel.kt | 2 +- .../deliveryverification/MasterKeyScreen.kt | 14 ++--- .../MasterKeyViewModel.kt | 14 ++--- .../navigation/ReceiverNavActions.kt | 2 +- .../navigation/model/ReceiverRoute.kt | 2 +- .../presentation/recordsbox/SenderEntry.kt | 8 +-- .../presentation/recordsbox/SenderRegistry.kt | 8 +-- .../senderdetail/SenderDetailScreen.kt | 2 +- .../senderdetail/SenderDetailUiState.kt | 2 +- .../senderdetail/SenderDetailViewModel.kt | 30 +++++----- .../MasterKeyScreenScreenshotTest.kt | 8 +-- .../MasterKeyViewModelTest.kt | 14 ++--- .../SenderDetailApprovedAtTest.kt | 8 +-- .../senderdetail/SenderDetailViewModelTest.kt | 4 +- 33 files changed, 161 insertions(+), 157 deletions(-) rename feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/{ReceiverAuthCodeDataStore.kt => ReceiverMasterKeyDataStore.kt} (84%) rename feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/{ReceiverAuthCodeDataStoreModule.kt => ReceiverMasterKeyDataStoreModule.kt} (81%) rename feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/{ReceiverAuthCodeDataSource.kt => ReceiverMasterKeyDataSource.kt} (71%) diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt b/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt index 99427d9efb..932ac6dcce 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt @@ -68,7 +68,7 @@ class ReceiverAdvancedAndroidTest { val masterKeyResults = ArrayDeque>() val receiverRepository = FakeReceiverRepository.strict().apply { - onSaveAuthCode = { authCodeState.value = it } + onSaveMasterKey = { masterKeyState.value = it } } val authRepository = FakeReceiverAuthRepository.strict().apply { @@ -159,9 +159,9 @@ class ReceiverAdvancedAndroidTest { val normalizedMasterKey = "3f2504e0-4f89-11d3-9a0c-0305e82c3301" val attached = checkNotNull(senderRegistry.findById(sender.id)) assertEquals(listOf(normalizedMasterKey), authRepository.verifiedMasterKeys) - assertEquals(listOf(normalizedMasterKey), receiverRepository.savedAuthCodes) - assertEquals(normalizedMasterKey, receiverRepository.authCodeState.value) - assertEquals(normalizedMasterKey, attached.authCode) + assertEquals(listOf(normalizedMasterKey), receiverRepository.savedMasterKeys) + assertEquals(normalizedMasterKey, receiverRepository.masterKeyState.value) + assertEquals(normalizedMasterKey, attached.masterKey) assertEquals("이발신", attached.realSenderName) assertEquals("가족", attached.relation) assertEquals(1, verifiedTransitions) diff --git a/app/src/main/java/com/afternote/afternote_fe/navigation/AppNavigationActions.kt b/app/src/main/java/com/afternote/afternote_fe/navigation/AppNavigationActions.kt index 9d66666006..ab59424faa 100644 --- a/app/src/main/java/com/afternote/afternote_fe/navigation/AppNavigationActions.kt +++ b/app/src/main/java/com/afternote/afternote_fe/navigation/AppNavigationActions.kt @@ -515,7 +515,7 @@ fun rememberAfternoteNavActions( * 수신자 서브그래프에 넘길 그래프 내부 [ReceiverNavActions] 구현체. * * 본인 확인 캐시 분기(Intro→MasterKey)는 nested 그래프 진입 후 `DeliveryVerificationFlowViewModel` 에서 - * 자동 처리되므로(#220) 본 actions 는 순수 네비게이션만 수행한다. authCode 같은 Repository 사이드이펙트는 + * 자동 처리되므로(#220) 본 actions 는 순수 네비게이션만 수행한다. masterKey 같은 Repository 사이드이펙트는 * 각 화면 ViewModel 에서 처리. */ @Composable diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStore.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStore.kt similarity index 84% rename from feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStore.kt rename to feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStore.kt index 047c9cea21..206de25044 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStore.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStore.kt @@ -5,4 +5,4 @@ import javax.inject.Qualifier /** Hilt 한정자: 수신 인증 코드 전용 `DataStore` 바인딩 (토큰용 DataStore와 구분). */ @Qualifier @Retention(AnnotationRetention.BINARY) -annotation class ReceiverAuthCodeDataStore +annotation class ReceiverMasterKeyDataStore diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStoreModule.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStoreModule.kt similarity index 81% rename from feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStoreModule.kt rename to feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStoreModule.kt index 092fbdf583..2e53b7e730 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverAuthCodeDataStoreModule.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/di/ReceiverMasterKeyDataStoreModule.kt @@ -12,11 +12,11 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -internal object ReceiverAuthCodeDataStoreModule { +internal object ReceiverMasterKeyDataStoreModule { @Provides @Singleton - @ReceiverAuthCodeDataStore - fun provideReceiverAuthCodeDataStore(registry: LocalStoreRegistry): DataStore = + @ReceiverMasterKeyDataStore + fun provideReceiverMasterKeyDataStore(registry: LocalStoreRegistry): DataStore = // name 은 저장 파일명 계약 (#912 필수 주의). 구 SharedPreferences XML 과 같은 이름이지만 // 자동 마이그레이션하지 않는다는 기존 결정이 있다 — 마이그레이션을 붙이지 말 것. registry.store(name = "afternote_receiver_auth", scope = StoreScope.SESSION) diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/dto/ReceiverAuthDto.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/dto/ReceiverAuthDto.kt index d92be13334..6be6120a09 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/dto/ReceiverAuthDto.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/dto/ReceiverAuthDto.kt @@ -107,6 +107,10 @@ data class ReceivedRecordBoxListDto( * 지킨다. 도메인으로 옮기는 건 지금 소비하는 것뿐이고, 나머지(`receiverName`·`relation`· * `recordStatus`·`viewStatus`)는 목록 화면이 이 API 로 옮겨갈 때(#607) 함께 올린다. * + * `accessCode` 는 **서버가 이 응답에서 부르는 이름**이라 DTO 에서는 그대로 받는다 — 같은 값을 + * `GET /users/receivers` 는 `authCode` 로, 헤더는 `X-Auth-Code` 로 부른다(2026-08-30 실측). 앱 안에서는 + * 사용자에게 보이는 말인 «마스터 키» 하나로 모으므로, 이름이 갈리는 것은 이 경계까지다 (#1554). + * * **nullable 은 BE 실코드로 판정한 것만 둔다.** OpenAPI 에 `requiredMode` 표기가 없어 문서만으로는 * 전 필드가 optional 로 보이지만(BE#269), 실제 계약은 이렇다. * @@ -177,7 +181,7 @@ fun DeliveryVerificationDto.toDomain(): DeliveryVerification = fun ReceivedRecordBoxDto.toDomain(): ReceivedRecordBox = ReceivedRecordBox( receiverId = receiverId, - accessCode = accessCode, + masterKey = accessCode, senderName = senderName, verificationStatus = verificationStatus?.let(DeliveryVerificationStatus::fromRaw) ?: DeliveryVerificationStatus.UNKNOWN, requestedAt = requestedAt, diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverAuthCodeDataSource.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverMasterKeyDataSource.kt similarity index 71% rename from feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverAuthCodeDataSource.kt rename to feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverMasterKeyDataSource.kt index b3dc111da1..94eec1aecd 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverAuthCodeDataSource.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/local/ReceiverMasterKeyDataSource.kt @@ -5,7 +5,7 @@ import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.core.stringPreferencesKey -import com.afternote.feature.receiver.data.di.ReceiverAuthCodeDataStore +import com.afternote.feature.receiver.data.di.ReceiverMasterKeyDataStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.map @@ -13,8 +13,8 @@ import java.io.IOException import javax.inject.Inject import javax.inject.Singleton -private object ReceiverAuthCodeKeys { - val AUTH_CODE = stringPreferencesKey("receiver_auth_code") +private object ReceiverMasterKeyKeys { + val MASTER_KEY = stringPreferencesKey("receiver_auth_code") } /** @@ -22,10 +22,10 @@ private object ReceiverAuthCodeKeys { * 도메인 [com.afternote.feature.receiver.domain.repository.ReceiverRepository]는 구현체에서만 이 클래스를 사용합니다. */ @Singleton -class ReceiverAuthCodeDataSource +class ReceiverMasterKeyDataSource @Inject constructor( - @param:ReceiverAuthCodeDataStore private val dataStore: DataStore, + @param:ReceiverMasterKeyDataStore private val dataStore: DataStore, ) { val savedCodeFlow: Flow = dataStore.data @@ -36,16 +36,16 @@ class ReceiverAuthCodeDataSource throw exception } }.map { preferences -> - preferences[ReceiverAuthCodeKeys.AUTH_CODE]?.takeIf { it.isNotBlank() } + preferences[ReceiverMasterKeyKeys.MASTER_KEY]?.takeIf { it.isNotBlank() } } suspend fun saveCode(code: String) { val trimmed = code.trim() dataStore.edit { preferences -> if (trimmed.isEmpty()) { - preferences.remove(ReceiverAuthCodeKeys.AUTH_CODE) + preferences.remove(ReceiverMasterKeyKeys.MASTER_KEY) } else { - preferences[ReceiverAuthCodeKeys.AUTH_CODE] = trimmed + preferences[ReceiverMasterKeyKeys.MASTER_KEY] = trimmed } } } diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/network/ReceiverAuthInterceptor.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/network/ReceiverAuthInterceptor.kt index ed0131960a..ea8b5bc848 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/network/ReceiverAuthInterceptor.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/network/ReceiverAuthInterceptor.kt @@ -1,6 +1,6 @@ package com.afternote.feature.receiver.data.network -import com.afternote.feature.receiver.data.local.ReceiverAuthCodeDataSource +import com.afternote.feature.receiver.data.local.ReceiverMasterKeyDataSource import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import okhttp3.Interceptor @@ -8,21 +8,21 @@ import okhttp3.Response import javax.inject.Inject /** - * `/receiver-auth/` 경로로 나가는 모든 요청에 [ReceiverAuthCodeDataSource]에 저장된 + * `/receiver-auth/` 경로로 나가는 모든 요청에 [ReceiverMasterKeyDataSource]에 저장된 * 인증 코드를 `X-Auth-Code` 헤더로 자동 부착한다. 코드가 없으면 헤더 없이 통과시켜 * 서버가 401을 반환하도록 둔다. */ class ReceiverAuthInterceptor @Inject constructor( - private val authCodeDataSource: ReceiverAuthCodeDataSource, + private val masterKeyDataSource: ReceiverMasterKeyDataSource, ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() if (!request.url.encodedPath.contains(RECEIVER_AUTH_PATH_SEGMENT)) { return chain.proceed(request) } - val code = runBlocking { authCodeDataSource.savedCodeFlow.first() } + val code = runBlocking { masterKeyDataSource.savedCodeFlow.first() } if (code.isNullOrBlank()) { return chain.proceed(request) } diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/IdentityVerificationRepositoryImpl.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/IdentityVerificationRepositoryImpl.kt index b911a63735..5024ac2aae 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/IdentityVerificationRepositoryImpl.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/IdentityVerificationRepositoryImpl.kt @@ -26,7 +26,7 @@ import javax.inject.Singleton * 그래서 저장 수명을 키 발급처와 같은 프로세스 수명으로 맞춘다. #912 가 도입했던 DataStore * (SESSION scope) 는 전역 boolean 시절의 「process death 후 유지」가 목적이었으나, 발신자별 * UUID 키에서는 그 유지가 도달 불가능해 디스크 비용만 남는다. 프로세스를 넘는 발신자 식별자 - * (예: BE 발급 sender id, 또는 마스터 키 authCode 의 비가역 파생값) 가 생기면 그때 영속을 되살린다. + * (예: BE 발급 sender id, 또는 마스터 키의 비가역 파생값) 가 생기면 그때 영속을 되살린다. * * 구 릴리스가 디스크에 남긴 전역 `identity_verified` boolean · `identity_verified_` 잔존값은 * 본 구현이 디스크를 아예 읽지 않으므로 구조적으로 어떤 발신자의 관문도 열 수 없다. diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverAuthRepositoryImpl.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverAuthRepositoryImpl.kt index 112859c559..857f426411 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverAuthRepositoryImpl.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverAuthRepositoryImpl.kt @@ -37,10 +37,10 @@ class ReceiverAuthRepositoryImpl constructor( private val api: ReceiverAuthApiService, ) : ReceiverAuthRepository { - override suspend fun verifyMasterKey(authCode: String): Result = + override suspend fun verifyMasterKey(masterKey: String): Result = runCatchingCancellable { try { - api.verifyMasterKey(ReceiverAuthVerifyRequestDto(authCode)).requireData().toDomain() + api.verifyMasterKey(ReceiverAuthVerifyRequestDto(masterKey)).requireData().toDomain() } catch (e: ApiException) { throw e.toReceiverServerFailure() } diff --git a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverRepositoryImpl.kt b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverRepositoryImpl.kt index 6ec8a41fae..ed0758210e 100644 --- a/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverRepositoryImpl.kt +++ b/feature/receiver/data/src/main/kotlin/com/afternote/feature/receiver/data/repositoryimpl/ReceiverRepositoryImpl.kt @@ -6,7 +6,7 @@ import androidx.paging.PagingData import com.afternote.core.common.reporting.ErrorReporter import com.afternote.core.common.result.runCatchingCancellable import com.afternote.core.network.model.requireData -import com.afternote.feature.receiver.data.local.ReceiverAuthCodeDataSource +import com.afternote.feature.receiver.data.local.ReceiverMasterKeyDataSource import com.afternote.feature.receiver.data.mapper.response.toDomain import com.afternote.feature.receiver.data.mapper.toDomainResult import com.afternote.feature.receiver.data.paging.ReceiverAfternotePagingSource @@ -26,7 +26,7 @@ import javax.inject.Singleton private const val PAGE_SIZE = 50 /** - * 인증 코드는 [ReceiverAuthCodeDataSource]에서 읽고·쓰고·지우며, REST 요청에는 ReceiverAuthInterceptor가 + * 인증 코드는 [ReceiverMasterKeyDataSource]에서 읽고·쓰고·지우며, REST 요청에는 ReceiverAuthInterceptor가 * `X-Auth-Code` 헤더를 자동 부착한다. 아직 별도 기능 repository로 이관되지 않은 export 항목은 * 폴백 값을 반환한다. */ @@ -34,17 +34,17 @@ private const val PAGE_SIZE = 50 class ReceiverRepositoryImpl @Inject constructor( - private val authCodeDataSource: ReceiverAuthCodeDataSource, + private val masterKeyDataSource: ReceiverMasterKeyDataSource, private val api: ReceiverAfternoteApiService, private val receiverAuthRepository: ReceiverAuthRepository, private val errorReporter: ErrorReporter, ) : ReceiverRepository { - override val authCodeFlow: Flow = authCodeDataSource.savedCodeFlow + override val masterKeyFlow: Flow = masterKeyDataSource.savedCodeFlow - override suspend fun currentAuthCode(): String? = authCodeFlow.first() + override suspend fun currentMasterKey(): String? = masterKeyFlow.first() - override suspend fun saveAuthCode(code: String) { - authCodeDataSource.saveCode(code) + override suspend fun saveMasterKey(code: String) { + masterKeyDataSource.saveCode(code) } override fun getPagedReceivedAfternotes(): Flow> = diff --git a/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceivedRecordBoxContractTest.kt b/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceivedRecordBoxContractTest.kt index 6d22530745..bf18730fff 100644 --- a/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceivedRecordBoxContractTest.kt +++ b/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceivedRecordBoxContractTest.kt @@ -40,7 +40,7 @@ class ReceivedRecordBoxContractTest { val box = boxes.single().toDomain() assertEquals(4L, box.receiverId) - assertEquals("59c04a15-1f4a-4b2e-9a0c-2f4e8d7b6c31", box.accessCode) + assertEquals("59c04a15-1f4a-4b2e-9a0c-2f4e8d7b6c31", box.masterKey) assertEquals("김혜성", box.senderName) assertEquals(DeliveryVerificationStatus.APPROVED, box.verificationStatus) assertEquals("2026-06-21T03:07:26", box.requestedAt) @@ -110,7 +110,7 @@ class ReceivedRecordBoxContractTest { .map { it.toDomain() } assertEquals(2, boxes.size) - val mine = boxes.first { it.accessCode == "bbbbbbbb-0000-4000-8000-000000000002" } + val mine = boxes.first { it.masterKey == "bbbbbbbb-0000-4000-8000-000000000002" } assertEquals("박경민", mine.senderName) assertEquals("2026-08-01T09:00:00", mine.approvedAt) } diff --git a/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceiverEmailAuthContractTest.kt b/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceiverEmailAuthContractTest.kt index f7369f72f6..9dff10243d 100644 --- a/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceiverEmailAuthContractTest.kt +++ b/feature/receiver/data/src/test/kotlin/com/afternote/feature/receiver/data/dto/ReceiverEmailAuthContractTest.kt @@ -17,8 +17,8 @@ import org.junit.Test * → `toDomain()` 을 통과시킨다 — Json 설정은 `NetworkModule.provideJson` 과 동일 * (ignoreUnknownKeys + coerceInputValues). * - * verify 성공 응답을 **accessCode 동봉·제거 두 형태 모두** 가드하는 이유: 서버가 마스터 키와 동일한 - * `accessCode` 를 응답에서 제거할 예정이라([ReceiverEmailAuthVerifyDto] 참고), 제거 배포가 언제 나가든 + * verify 성공 응답을 **masterKey 동봉·제거 두 형태 모두** 가드하는 이유: 서버가 마스터 키와 동일한 + * `masterKey` 를 응답에서 제거할 예정이라([ReceiverEmailAuthVerifyDto] 참고), 제거 배포가 언제 나가든 * 파싱이 깨지지 않아야 한다 (#454). * * 에러 응답(404 code 1901 / 400 code 1902·1903)은 HTTP 4xx 라 Retrofit CallAdapter가 가로채는 경로 — @@ -32,7 +32,7 @@ class ReceiverEmailAuthContractTest { } @Test - fun `email-verify 성공 응답(accessCode 동봉) - 잔여 키를 무시하고 도메인 모델까지 도달`() { + fun `email-verify 성공 응답(masterKey 동봉) - 잔여 키를 무시하고 도메인 모델까지 도달`() { val payload = """{"status":200,"code":200,"message":"성공","data":{"receiverId":3,"receiverName":"큐에이수신자","senderName":"큐에이발신자","accessCode":"123e4567-e89b-12d3-a456-426614174000"}}""" @@ -44,7 +44,7 @@ class ReceiverEmailAuthContractTest { } @Test - fun `email-verify 성공 응답(accessCode 제거 후) - 디코드 성공`() { + fun `email-verify 성공 응답(masterKey 제거 후) - 디코드 성공`() { val payload = """{"status":200,"code":200,"message":"성공","data":{"receiverId":3,"receiverName":"큐에이수신자","senderName":"큐에이발신자"}}""" diff --git a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/model/ReceiverAuthModels.kt b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/model/ReceiverAuthModels.kt index e063865f8e..5962bdea6b 100644 --- a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/model/ReceiverAuthModels.kt +++ b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/model/ReceiverAuthModels.kt @@ -56,18 +56,18 @@ enum class DeliveryVerificationStatus { * * 서버는 **마스터 키가 아니라 그 키가 가리키는 수신자의 이메일**을 권한 근거로 삼는다 — 같은 이메일로 * 등록된 기록함이 여러 발신자 것이어도 한 번에 내려온다. 그래서 특정 발신자의 칸을 고르려면 - * 화면이 들고 있는 마스터 키와 [accessCode] 를 맞춰야 한다. + * 화면이 들고 있는 마스터 키와 [masterKey] 를 맞춰야 한다. * * 지금 이 모델을 읽는 곳은 발신자 상세의 승인일 표시 하나다(#612). 목록 화면이 이 API 로 옮겨갈 때 * (#607) `receiverName`·`relation`·`recordStatus`·`viewStatus` 를 여기에 더한다 — 서버는 이미 준다. * - * @property accessCode 이 칸을 여는 접근 코드. 발신자가 수신자에게 건넨 마스터 키와 같은 값이다. + * @property masterKey 이 칸을 여는 접근 코드. 발신자가 수신자에게 건넨 마스터 키와 같은 값이다. * @property requestedAt 열람 신청일. 서버 ISO-8601 raw — 표시 형식 변환은 presentation 책임. * @property approvedAt 열람 승인일. **서버는 승인 상태일 때만 채운다** — 신청 전·심사 중·반려는 null. */ data class ReceivedRecordBox( val receiverId: Long, - val accessCode: String, + val masterKey: String, val senderName: String, val verificationStatus: DeliveryVerificationStatus, val requestedAt: String?, diff --git a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverAuthRepository.kt b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverAuthRepository.kt index c746254ec4..43c3a7901d 100644 --- a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverAuthRepository.kt +++ b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverAuthRepository.kt @@ -13,18 +13,18 @@ import com.afternote.feature.receiver.domain.model.SenderMessageInfo * 기존 `ReceiverRepository` 는 인증된 수신자가 사용하는 일반 조회 (after-notes 등) 책임. * 본 Repository 는 인증 자체 + 서류 제출/검증 + sender 메시지 조회를 담당한다. * - * 인증 코드 저장은 `ReceiverRepository.saveAuthCode` 를 사용하며, + * 인증 코드 저장은 `ReceiverRepository.saveMasterKey` 를 사용하며, * 저장된 코드는 `ReceiverAuthInterceptor` 가 `X-Auth-Code` 헤더로 자동 부착한다. * (둘 다 feature:afternote 쪽이라 이 모듈에서 KDoc 링크로 참조할 수 없다 — 의존 방향이 반대.) */ interface ReceiverAuthRepository { /** - * 발신자가 발급한 마스터 키([authCode])로 수신자 신원을 확인한다. + * 발신자가 발급한 마스터 키([masterKey])로 수신자 신원을 확인한다. * * 성공하면 이 키가 이후 요청의 `X-Auth-Code` 헤더로 재사용된다 (사실상 수신자 세션). * 서버 거절은 `ReceiverFailure.UserRejection` 또는 `ReceiverFailure.UnexpectedServerFailure` 로 번역된다. */ - suspend fun verifyMasterKey(authCode: String): Result + suspend fun verifyMasterKey(masterKey: String): Result /** * 수신자 본인 확인 — 수신자 레코드에 등록된 [email] 로 6자리 인증번호 발송. @@ -73,7 +73,7 @@ interface ReceiverAuthRepository { * * 서버의 권한 근거가 키가 아니라 **그 키가 가리키는 수신자의 이메일**이라, 같은 이메일로 등록된 * 다른 발신자의 칸까지 함께 온다. 특정 발신자의 칸이 필요하면 호출부가 - * [ReceivedRecordBox.accessCode] 로 골라야 한다. + * [ReceivedRecordBox.masterKey] 로 골라야 한다. */ suspend fun getReceivedRecordBoxes(): Result> } diff --git a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverDeliveryDocumentUploadRepository.kt b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverDeliveryDocumentUploadRepository.kt index bc038a6a05..0482f7a430 100644 --- a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverDeliveryDocumentUploadRepository.kt +++ b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverDeliveryDocumentUploadRepository.kt @@ -8,7 +8,7 @@ package com.afternote.feature.receiver.domain.repository * 호출한다 (도메인 레이어가 안드로이드 API 에 의존하지 않도록). * * 업로드 + presigned URL 요청은 모두 `receiver-auth/` 인증 컨텍스트가 필요하므로, 호출 시점에 - * [ReceiverRepository.saveAuthCode] 로 해당 발신자의 authCode 가 세팅돼 있어야 한다 (인터셉터가 헤더 부착). + * [ReceiverRepository.saveMasterKey] 로 해당 발신자의 masterKey 가 세팅돼 있어야 한다 (인터셉터가 헤더 부착). */ interface ReceiverDeliveryDocumentUploadRepository { /** diff --git a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverRepository.kt b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverRepository.kt index e1013fae0a..b1aaf38ddd 100644 --- a/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverRepository.kt +++ b/feature/receiver/domain/src/main/java/com/afternote/feature/receiver/domain/repository/ReceiverRepository.kt @@ -16,13 +16,13 @@ import kotlinx.coroutines.flow.Flow */ interface ReceiverRepository { /** 저장된 인증 코드 스트림(없거나 공백만 있으면 null 방출). */ - val authCodeFlow: Flow + val masterKeyFlow: Flow /** 단발 조회; UI 스레드에서는 코루틴 안에서 호출하세요. */ - suspend fun currentAuthCode(): String? + suspend fun currentMasterKey(): String? /** 사용자가 입력·검증한 코드를 저장합니다. 제거는 로그아웃 일괄 정리(SESSION scope, #912)가 담당합니다. */ - suspend fun saveAuthCode(code: String) + suspend fun saveMasterKey(code: String) /** * 수신 애프터노트 스트림. 서버는 페이지네이션 미지원이므로 단일 페이지로 받지만, diff --git a/feature/receiver/domain/src/test/java/com/afternote/feature/receiver/domain/testing/FakeReceiverRepositoriesTest.kt b/feature/receiver/domain/src/test/java/com/afternote/feature/receiver/domain/testing/FakeReceiverRepositoriesTest.kt index 905ba115e8..6bbb2eb6b9 100644 --- a/feature/receiver/domain/src/test/java/com/afternote/feature/receiver/domain/testing/FakeReceiverRepositoriesTest.kt +++ b/feature/receiver/domain/src/test/java/com/afternote/feature/receiver/domain/testing/FakeReceiverRepositoriesTest.kt @@ -16,35 +16,35 @@ import org.junit.Test class FakeReceiverRepositoriesTest { @Test fun `인증 코드 저장은 호출 원문을 기록하고 정규화한 상태를 flow와 단발 조회에 공유한다`() { - val repository = FakeReceiverRepository(initialAuthCode = " initial ") + val repository = FakeReceiverRepository(initialMasterKey = " initial ") - assertEquals("initial", repository.authCodeState.value) - assertNull(FakeReceiverRepository(initialAuthCode = " ").authCodeState.value) + assertEquals("initial", repository.masterKeyState.value) + assertNull(FakeReceiverRepository(initialMasterKey = " ").masterKeyState.value) - runBlocking { repository.saveAuthCode(" next-code ") } + runBlocking { repository.saveMasterKey(" next-code ") } - assertEquals(listOf(" next-code "), repository.savedAuthCodes) - assertEquals("next-code", repository.authCodeState.value) - assertEquals("next-code", runBlocking { repository.currentAuthCode() }) - assertSame(repository.authCodeState, repository.authCodeFlow) + assertEquals(listOf(" next-code "), repository.savedMasterKeys) + assertEquals("next-code", repository.masterKeyState.value) + assertEquals("next-code", runBlocking { repository.currentMasterKey() }) + assertSame(repository.masterKeyState, repository.masterKeyFlow) - runBlocking { repository.saveAuthCode(" ") } + runBlocking { repository.saveMasterKey(" ") } - assertNull(repository.authCodeState.value) + assertNull(repository.masterKeyState.value) } @Test fun `ReceiverRepository onX는 기록 뒤 기본 메모리 변경을 대체한다`() { val repository = FakeReceiverRepository( - initialAuthCode = "initial", - onSaveAuthCode = {}, + initialMasterKey = "initial", + onSaveMasterKey = {}, ) - runBlocking { repository.saveAuthCode("replacement") } + runBlocking { repository.saveMasterKey("replacement") } - assertEquals(listOf("replacement"), repository.savedAuthCodes) - assertEquals("initial", repository.authCodeState.value) + assertEquals(listOf("replacement"), repository.savedMasterKeys) + assertEquals("initial", repository.masterKeyState.value) } @Test @@ -143,7 +143,7 @@ class FakeReceiverRepositoriesTest { val authRepository = FakeReceiverAuthRepository.strict() assertThrows(IllegalStateException::class.java) { - receiverRepository.authCodeFlow + receiverRepository.masterKeyFlow } assertThrows(IllegalStateException::class.java) { runBlocking { authRepository.getSenderMessage() } diff --git a/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverAuthRepository.kt b/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverAuthRepository.kt index a1befdf093..f2c088a7db 100644 --- a/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverAuthRepository.kt +++ b/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverAuthRepository.kt @@ -52,9 +52,9 @@ class FakeReceiverAuthRepository( val getReceivedRecordBoxesCalls: Int get() = recordBoxesCounter.get() - override suspend fun verifyMasterKey(authCode: String): Result { - verifiedMasterKeys += authCode - onVerifyMasterKey?.let { return it(authCode) } + override suspend fun verifyMasterKey(masterKey: String): Result { + verifiedMasterKeys += masterKey + onVerifyMasterKey?.let { return it(masterKey) } return Result.success(identity) } diff --git a/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverRepository.kt b/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverRepository.kt index 6975ec84c0..84b86463d5 100644 --- a/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverRepository.kt +++ b/feature/receiver/domain/src/testFixtures/kotlin/com/afternote/feature/receiver/domain/testing/FakeReceiverRepository.kt @@ -17,19 +17,19 @@ import java.util.concurrent.atomic.AtomicInteger /** * [ReceiverRepository] fake 정본 (#1030, #1042). * - * [authCodeState] 에 값을 넣으면 [authCodeFlow] 구독자와 [currentAuthCode] 가 같은 값을 본다. + * [masterKeyState] 에 값을 넣으면 [masterKeyFlow] 구독자와 [currentMasterKey] 가 같은 값을 본다. * 저장소 기본 동작으로 표현하기 어려운 실패·경합·응답 순서는 `onX` 로 갈아끼운다. */ class FakeReceiverRepository( - initialAuthCode: String? = null, + initialMasterKey: String? = null, var afterNotes: AfterNotesListResult = EMPTY_AFTER_NOTES, details: Map = emptyMap(), var exportBundle: ReceivedExportBundle = ReceivedExportBundle(), var senderMessage: SenderMessageInfo? = null, var pagedAfterNotes: Flow> = flowOf(PagingData.empty()), - var onAuthCodeFlow: (() -> Flow)? = null, - var onCurrentAuthCode: (suspend () -> String?)? = null, - var onSaveAuthCode: (suspend (String) -> Unit)? = null, + var onMasterKeyFlow: (() -> Flow)? = null, + var onCurrentMasterKey: (suspend () -> String?)? = null, + var onSaveMasterKey: (suspend (String) -> Unit)? = null, var onGetPagedReceivedAfternotes: (() -> Flow>)? = null, var onGetReceivedAfterNotes: (suspend () -> Result)? = null, var onGetReceivedAfternoteDetail: (suspend (Long) -> Result)? = null, @@ -38,25 +38,25 @@ class FakeReceiverRepository( var onLoadSenderMessage: (suspend () -> Result)? = null, ) : ReceiverRepository { /** 테스트가 직접 값을 밀어 넣는 수신자 인증 코드 상태. */ - val authCodeState = MutableStateFlow(initialAuthCode?.trim()?.takeIf(String::isNotEmpty)) + val masterKeyState = MutableStateFlow(initialMasterKey?.trim()?.takeIf(String::isNotEmpty)) val details = ConcurrentHashMap(details) - val savedAuthCodes = CopyOnWriteArrayList() + val savedMasterKeys = CopyOnWriteArrayList() val requestedDetailIds = CopyOnWriteArrayList() val savedBundles = CopyOnWriteArrayList() - private val authCodeFlowCounter = AtomicInteger() - private val currentAuthCodeCounter = AtomicInteger() + private val masterKeyFlowCounter = AtomicInteger() + private val currentMasterKeyCounter = AtomicInteger() private val pagedAfterNotesCounter = AtomicInteger() private val afterNotesCounter = AtomicInteger() private val downloadCounter = AtomicInteger() private val senderMessageCounter = AtomicInteger() - val authCodeFlowCalls: Int - get() = authCodeFlowCounter.get() + val masterKeyFlowCalls: Int + get() = masterKeyFlowCounter.get() - val currentAuthCodeCalls: Int - get() = currentAuthCodeCounter.get() + val currentMasterKeyCalls: Int + get() = currentMasterKeyCounter.get() val getPagedReceivedAfternotesCalls: Int get() = pagedAfterNotesCounter.get() @@ -70,25 +70,25 @@ class FakeReceiverRepository( val loadSenderMessageCalls: Int get() = senderMessageCounter.get() - override val authCodeFlow: Flow + override val masterKeyFlow: Flow get() { - authCodeFlowCounter.incrementAndGet() - return onAuthCodeFlow?.invoke() ?: authCodeState + masterKeyFlowCounter.incrementAndGet() + return onMasterKeyFlow?.invoke() ?: masterKeyState } - override suspend fun currentAuthCode(): String? { - currentAuthCodeCounter.incrementAndGet() - onCurrentAuthCode?.let { return it() } - return authCodeState.value + override suspend fun currentMasterKey(): String? { + currentMasterKeyCounter.incrementAndGet() + onCurrentMasterKey?.let { return it() } + return masterKeyState.value } - override suspend fun saveAuthCode(code: String) { - savedAuthCodes += code - onSaveAuthCode?.let { + override suspend fun saveMasterKey(code: String) { + savedMasterKeys += code + onSaveMasterKey?.let { it(code) return } - authCodeState.value = code.trim().takeIf(String::isNotEmpty) + masterKeyState.value = code.trim().takeIf(String::isNotEmpty) } override fun getPagedReceivedAfternotes(): Flow> { @@ -133,13 +133,13 @@ class FakeReceiverRepository( companion object { private val EMPTY_AFTER_NOTES = AfterNotesListResult(items = emptyList(), totalCount = 0) - /** 모든 계약 경로를 닫되 [authCodeState] 자체는 테스트가 준비 상태로 쓸 수 있다. */ - fun strict(initialAuthCode: String? = null): FakeReceiverRepository = + /** 모든 계약 경로를 닫되 [masterKeyState] 자체는 테스트가 준비 상태로 쓸 수 있다. */ + fun strict(initialMasterKey: String? = null): FakeReceiverRepository = FakeReceiverRepository( - initialAuthCode = initialAuthCode, - onAuthCodeFlow = { unexpectedCall("ReceiverRepository.authCodeFlow") }, - onCurrentAuthCode = { unexpectedCall("ReceiverRepository.currentAuthCode") }, - onSaveAuthCode = { unexpectedCall("ReceiverRepository.saveAuthCode") }, + initialMasterKey = initialMasterKey, + onMasterKeyFlow = { unexpectedCall("ReceiverRepository.authCodeFlow") }, + onCurrentMasterKey = { unexpectedCall("ReceiverRepository.currentAuthCode") }, + onSaveMasterKey = { unexpectedCall("ReceiverRepository.saveAuthCode") }, onGetPagedReceivedAfternotes = { unexpectedCall("ReceiverRepository.getPagedReceivedAfternotes") }, diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/DeliveryVerificationFlowViewModel.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/DeliveryVerificationFlowViewModel.kt index 8ae54cdbc5..7fe6935b74 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/DeliveryVerificationFlowViewModel.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/DeliveryVerificationFlowViewModel.kt @@ -23,7 +23,7 @@ import javax.inject.Inject * 자식이 직접 의존하지 않고 flow VM 통해 결정 * * 후속(2차 PR 이후) 으로 옮길 책임: - * - `authCode`·`ReceiverIdentity` 등 누적 흐름 상태 보유 + * - `masterKey`·`ReceiverIdentity` 등 누적 흐름 상태 보유 * - [com.afternote.feature.receiver.presentation.recordsbox.SenderRegistry.attachIdentity] 호출 시점 위임 * - [IdentityVerificationRepository] 자체의 흡수·싱글톤 제거 */ diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreen.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreen.kt index 0cd93d7670..123a6aa7dd 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreen.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreen.kt @@ -29,7 +29,7 @@ import com.afternote.feature.receiver.presentation.deliveryverification.componen /** * 마스터 키 입력 화면(design 5) — 진행 인디케이터 2/3 + 단일 입력 + "다음" CTA (이슈 #215). * - * `verify(authCode)` 성공 시 SenderRegistry 에 authCode·신원 결합 + 글로벌 헤더 저장 → [onVerified] 로 서류 업로드 단계 진입. + * `verify(masterKey)` 성공 시 SenderRegistry 에 masterKey·신원 결합 + 글로벌 헤더 저장 → [onVerified] 로 서류 업로드 단계 진입. * * 메모리 정책상 ViewModel 은 TextFieldState 미보유. UI 가 `rememberTextFieldState` 로 인스턴스를 들고 있다가 submit 시점에만 값을 전달. */ @@ -42,7 +42,7 @@ fun MasterKeyScreen( viewModel: MasterKeyViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - val authCodeState = rememberTextFieldState() + val masterKeyState = rememberTextFieldState() val snackbarHostState = remember { SnackbarHostState() } LaunchedEffect(uiState.isVerified) { @@ -62,18 +62,18 @@ fun MasterKeyScreen( } MasterKeyScreenContent( - authCodeState = authCodeState, + masterKeyState = masterKeyState, isSubmitting = uiState.isSubmitting, snackbarHostState = snackbarHostState, onBackClick = onBackClick, - onSubmitClick = { viewModel.submit(senderId, authCodeState.text.toString()) }, + onSubmitClick = { viewModel.submit(senderId, masterKeyState.text.toString()) }, modifier = modifier, ) } @Composable internal fun MasterKeyScreenContent( - authCodeState: TextFieldState, + masterKeyState: TextFieldState, isSubmitting: Boolean, snackbarHostState: SnackbarHostState, onBackClick: () -> Unit, @@ -81,7 +81,7 @@ internal fun MasterKeyScreenContent( modifier: Modifier = Modifier, ) { val isInputFilled = - authCodeState.text + masterKeyState.text .toString() .trim() .isNotEmpty() @@ -115,7 +115,7 @@ internal fun MasterKeyScreenContent( Spacer(modifier = Modifier.height(16.dp)) AfternoteTextField( - state = authCodeState, + state = masterKeyState, placeholder = stringResource(R.string.receiver_verify_master_key_placeholder), modifier = Modifier.fillMaxWidth().imePadding(), ) diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModel.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModel.kt index d957228ea7..b14127d4fb 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModel.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModel.kt @@ -21,12 +21,12 @@ import kotlinx.coroutines.launch import javax.inject.Inject /** - * 마스터 키 입력 화면(5) ViewModel — 발신자별 authCode 검증 (이슈 #215, #220 후속). + * 마스터 키 입력 화면(5) ViewModel — 발신자별 masterKey 검증 (이슈 #215, #220 후속). * - * `verifyMasterKey(authCode)` 성공 시: - * 1) [ReceiverRepository.saveAuthCode] 로 글로벌 헤더 컨텍스트에 저장 (이후 서류 업로드·신청 제출 API 가 + * `verifyMasterKey(masterKey)` 성공 시: + * 1) [ReceiverRepository.saveMasterKey] 로 글로벌 헤더 컨텍스트에 저장 (이후 서류 업로드·신청 제출 API 가 * 동일 발신자 컨텍스트로 호출되도록). - * 2) [SenderRegistry.attachIdentity] 로 카드에 authCode + ReceiverIdentity 결합. + * 2) [SenderRegistry.attachIdentity] 로 카드에 masterKey + ReceiverIdentity 결합. * 3) [MasterKeyUiState.isVerified] 를 true 로 갱신 → UI 가 다음 단계(서류 업로드) 로 이동 후 * [onVerifiedConsumed] 로 소비 처리. * @@ -53,10 +53,10 @@ class MasterKeyViewModel fun submit( senderId: String, - authCode: String, + masterKey: String, ) { // BE @Pattern 은 소문자 UUID 만 받는다 — 대소문자 무의미 값이라 대문자 입력은 거절 대신 정규화한다 (#887). - val trimmed = authCode.trim().lowercase() + val trimmed = masterKey.trim().lowercase() if (trimmed.isEmpty() || _uiState.value.isSubmitting) return if (!MASTER_KEY_UUID_REGEX.matches(trimmed)) { _uiState.update { @@ -70,7 +70,7 @@ class MasterKeyViewModel receiverAuthRepository .verifyMasterKey(trimmed) .onSuccess { identity -> - receiverRepository.saveAuthCode(trimmed) + receiverRepository.saveMasterKey(trimmed) senderRegistry.attachIdentity(senderId, trimmed, identity) _uiState.update { it.copy(isSubmitting = false, isVerified = true) } }.onFailure { throwable -> diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/ReceiverNavActions.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/ReceiverNavActions.kt index 1df296900e..4270194339 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/ReceiverNavActions.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/ReceiverNavActions.kt @@ -46,7 +46,7 @@ interface ReceiverNavActions { fun popToReceivedRecords() /** - * 발신자 상세(12)의 "기록 열람하기" → 수신자 홈 진입. 발신자 컨텍스트(authCode) 복원은 + * 발신자 상세(12)의 "기록 열람하기" → 수신자 홈 진입. 발신자 컨텍스트(masterKey) 복원은 * `SenderDetailViewModel.openReceiverHome` 이 담당하므로 본 액션은 순수 네비게이션만 수행한다. */ fun navigateToReceiverHome() diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/model/ReceiverRoute.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/model/ReceiverRoute.kt index 15101620b5..9cebead8d1 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/model/ReceiverRoute.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/navigation/model/ReceiverRoute.kt @@ -76,7 +76,7 @@ sealed interface ReceiverRoute { /** * 열람 신청 1단계: 마스터 키 입력(5). * - * `verify(authCode)` 응답 성공 시 ReceiverIdentity 를 (부모 라우트의) senderId 카드에 결합하고 다음 단계로. + * `verify(masterKey)` 응답 성공 시 ReceiverIdentity 를 (부모 라우트의) senderId 카드에 결합하고 다음 단계로. */ @Serializable data object MasterKeyRoute : ReceiverRoute diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderEntry.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderEntry.kt index 85f0f1a3ff..fce591d141 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderEntry.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderEntry.kt @@ -7,10 +7,10 @@ import com.afternote.feature.receiver.domain.model.DeliveryVerificationStatus * 받은 기록함 카드 한 줄의 표시 데이터. * * `id` 는 클라 로컬에서 발급하는 식별자(백엔드 발신자 ID 와 별개). 서버 매칭은 마스터 키 검증 시점에 - * `verify(authCode)` 응답으로 이뤄지므로, 카드 자체는 사용자가 부여한 *별칭* 만 보관한다. + * `verify(masterKey)` 응답으로 이뤄지므로, 카드 자체는 사용자가 부여한 *별칭* 만 보관한다. * - * `authCode` 는 마스터 키 검증 성공 후 채워지며, "기록 열람하기" 진입 시 [com.afternote.feature.afternote - * .domain.repository.receiver.ReceiverRepository.saveAuthCode] 로 글로벌 헤더 컨텍스트에 복원한다. + * `masterKey` 는 마스터 키 검증 성공 후 채워지며, "기록 열람하기" 진입 시 [com.afternote.feature.afternote + * .domain.repository.receiver.ReceiverRepository.saveMasterKey] 로 글로벌 헤더 컨텍스트에 복원한다. * `realSenderName`·`relation` 은 [com.afternote.feature.receiver.domain.model.ReceiverIdentity] * 응답에서 수신한 값으로 발신자 상세(11·12)의 인사말 및 관계 표기에 사용한다. * @@ -21,7 +21,7 @@ import com.afternote.feature.receiver.domain.model.DeliveryVerificationStatus data class SenderEntry( val id: String, val name: String, - val authCode: String? = null, + val masterKey: String? = null, val realSenderName: String? = null, val relation: String? = null, val verificationStatus: DeliveryVerificationStatus? = null, diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderRegistry.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderRegistry.kt index 0236e1bbec..398c895cd1 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderRegistry.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/recordsbox/SenderRegistry.kt @@ -44,17 +44,17 @@ class SenderRegistry fun findById(id: String): SenderEntry? = _senders.value.firstOrNull { it.id == id } /** - * 마스터 키 검증 성공 직후 호출. authCode + verify 응답 정보를 카드에 결합한다. 이후 - * "기록 열람하기"(12) 진입 시 이 authCode 를 ReceiverRepository 에 복원해 헤더 컨텍스트를 잡는다. + * 마스터 키 검증 성공 직후 호출. masterKey + verify 응답 정보를 카드에 결합한다. 이후 + * "기록 열람하기"(12) 진입 시 이 masterKey 를 ReceiverRepository 에 복원해 헤더 컨텍스트를 잡는다. */ fun attachIdentity( id: String, - authCode: String, + masterKey: String, identity: ReceiverIdentity, ): SenderEntry? = updateById(id) { entry -> entry.copy( - authCode = authCode, + masterKey = masterKey, realSenderName = identity.senderName, relation = identity.relation, ) diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailScreen.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailScreen.kt index b2fb66f990..0be1540bd1 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailScreen.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailScreen.kt @@ -47,7 +47,7 @@ import com.afternote.feature.receiver.presentation.R * 3. 정보 박스 4 행: 기록 / 상태 / 신청일 / 승인일. * 4. 하단 CTA: "열람 신청하기" (NotRequested/Pending/Rejected) 또는 "기록 열람하기" (Approved). * - * "기록 열람하기" 클릭 시 ViewModel 이 글로벌 헤더에 authCode 를 복원한 뒤 + * "기록 열람하기" 클릭 시 ViewModel 이 글로벌 헤더에 masterKey 를 복원한 뒤 * [SenderDetailUiState.Success.shouldOpenReceiverHome] 를 true 로 갱신. 본 화면이 [LaunchedEffect] 로 받아 * [onOpenReceiverHome] (순수 네비게이션) 호출 후 [SenderDetailViewModel.onOpenReceiverHomeConsumed] 로 reset. */ diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailUiState.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailUiState.kt index d7ca078d30..f44d41b915 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailUiState.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailUiState.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Immutable /** * 발신자 상세(designs 11·12) UI 상태. * - * 카드 별칭은 SenderRegistry, 신원(실명) 은 `verify(authCode)` 응답, 신청·승인 일시는 + * 카드 별칭은 SenderRegistry, 신원(실명) 은 `verify(masterKey)` 응답, 신청·승인 일시는 * `getDeliveryVerificationStatus()` 응답을 결합해 정보 박스 4 행 + CTA 분기 데이터를 만든다. */ sealed interface SenderDetailUiState { diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModel.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModel.kt index 0d067447c0..8481e90073 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModel.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModel.kt @@ -27,11 +27,11 @@ import javax.inject.Inject /** * 발신자 상세(designs 11·12) ViewModel. * - * 진입 시점에 SenderRegistry 에서 카드 식별 + authCode 를 얻고, authCode 가 있으면 - * [ReceiverRepository.saveAuthCode] 로 글로벌 헤더 컨텍스트를 교체한 뒤 + * 진입 시점에 SenderRegistry 에서 카드 식별 + masterKey 를 얻고, masterKey 가 있으면 + * [ReceiverRepository.saveMasterKey] 로 글로벌 헤더 컨텍스트를 교체한 뒤 * [ReceiverAuthRepository.getDeliveryVerificationStatus] 로 상태를 받아 정보 박스 데이터를 만든다. * - * authCode 가 없으면(마스터 키 미입력) 무조건 [SenderVerificationState.NotRequested] — API 호출 자체 생략. + * masterKey 가 없으면(마스터 키 미입력) 무조건 [SenderVerificationState.NotRequested] — API 호출 자체 생략. */ @HiltViewModel class SenderDetailViewModel @@ -83,17 +83,17 @@ class SenderDetailViewModel } /** - * "기록 열람하기"(디자인 12) 트리거 — 글로벌 헤더에 해당 발신자 authCode 를 복원한 뒤 + * "기록 열람하기"(디자인 12) 트리거 — 글로벌 헤더에 해당 발신자 masterKey 를 복원한 뒤 * [SenderDetailUiState.Success.shouldOpenReceiverHome] 플래그를 true 로 갱신. * UI 가 LaunchedEffect 로 수신자 홈 이동 후 [onOpenReceiverHomeConsumed] 로 reset. * - * authCode 가 없는 경우(미인증) 호출되어선 안 되지만 방어적으로 no-op. + * masterKey 가 없는 경우(미인증) 호출되어선 안 되지만 방어적으로 no-op. */ fun openReceiverHome() { - val authCode = senderRegistry.findById(senderId)?.authCode - if (authCode.isNullOrBlank()) return + val masterKey = senderRegistry.findById(senderId)?.masterKey + if (masterKey.isNullOrBlank()) return viewModelScope.launch { - receiverRepository.saveAuthCode(authCode) + receiverRepository.saveMasterKey(masterKey) _uiState.update { current -> if (current is SenderDetailUiState.Success) { current.copy(shouldOpenReceiverHome = true) @@ -158,7 +158,7 @@ class SenderDetailViewModel * * `delivery-verification/status` 응답에는 승인 일시가 없다 — 그 값을 주는 건 `record-boxes` 뿐이라 * 화면이 오래 «승인 기록이 없습니다» 로 비어 있었다. 서버는 같은 이메일에 등록된 기록함을 모두 - * 내려주므로 지금 보고 있는 발신자의 칸은 [ReceivedRecordBox.accessCode] 로 골라낸다. + * 내려주므로 지금 보고 있는 발신자의 칸은 [ReceivedRecordBox.masterKey] 로 골라낸다. * * **이건 서버가 고칠 때까지의 우회다 — BE#96.** 한 줄을 표시하려고 목록 API 를 통째로 왕복하고 * 있다. `status` 응답이 `approvedAt` 을 내려주기 시작하면 이 함수와 호출부, 골라내는 코드가 @@ -172,7 +172,7 @@ class SenderDetailViewModel */ private suspend fun resolveApprovedAt( status: DeliveryVerificationStatus, - authCode: String, + masterKey: String, ): String? { if (status != DeliveryVerificationStatus.APPROVED) return null return receiverAuthRepository @@ -180,15 +180,15 @@ class SenderDetailViewModel .onFailure { e -> errorReporter.recordAfternoteFailure(AfternoteFailureStage.SENDER_STATUS_LOAD, e) }.getOrNull() - ?.firstOrNull { it.accessCode == authCode } + ?.firstOrNull { it.masterKey == masterKey } ?.approvedAt } private suspend fun resolveState(sender: SenderEntry): SenderDetailUiState { val displayName = sender.name - val authCode = sender.authCode + val masterKey = sender.masterKey - if (authCode.isNullOrBlank()) { + if (masterKey.isNullOrBlank()) { return SenderDetailUiState.Success( displayName = displayName, verification = SenderVerificationState.NotRequested, @@ -197,14 +197,14 @@ class SenderDetailViewModel ) } - receiverRepository.saveAuthCode(authCode) + receiverRepository.saveMasterKey(masterKey) val statusResult = receiverAuthRepository.getDeliveryVerificationStatus() return statusResult.fold( onSuccess = { verification -> senderRegistry.updateVerificationStatus(sender.id, verification.status) verification.toSuccessState( displayName = displayName, - approvedAt = resolveApprovedAt(verification.status, authCode), + approvedAt = resolveApprovedAt(verification.status, masterKey), ) }, onFailure = { e -> diff --git a/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreenScreenshotTest.kt b/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreenScreenshotTest.kt index 56830851aa..13d3aab358 100644 --- a/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreenScreenshotTest.kt +++ b/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyScreenScreenshotTest.kt @@ -16,7 +16,7 @@ import com.android.tools.screenshot.PreviewTest internal fun masterKeyScreenEmptyScreenshot() { AfternoteTheme { MasterKeyScreenContent( - authCodeState = rememberTextFieldState(), + masterKeyState = rememberTextFieldState(), isSubmitting = false, snackbarHostState = remember { SnackbarHostState() }, onBackClick = {}, @@ -31,7 +31,7 @@ internal fun masterKeyScreenEmptyScreenshot() { internal fun masterKeyScreenFilledScreenshot() { AfternoteTheme { MasterKeyScreenContent( - authCodeState = rememberTextFieldState("ABC-DEF-GHI"), + masterKeyState = rememberTextFieldState("ABC-DEF-GHI"), isSubmitting = false, snackbarHostState = remember { SnackbarHostState() }, onBackClick = {}, @@ -51,7 +51,7 @@ internal fun masterKeyScreenFilledScreenshot() { internal fun masterKeyScreenFilledCompactScreenshot() { AfternoteTheme { MasterKeyScreenContent( - authCodeState = rememberTextFieldState("ABC-DEF-GHI"), + masterKeyState = rememberTextFieldState("ABC-DEF-GHI"), isSubmitting = false, snackbarHostState = remember { SnackbarHostState() }, onBackClick = {}, @@ -71,7 +71,7 @@ internal fun masterKeyScreenFilledCompactScreenshot() { internal fun masterKeyScreenFilledLargeFontScreenshot() { AfternoteTheme { MasterKeyScreenContent( - authCodeState = rememberTextFieldState("ABC-DEF-GHI"), + masterKeyState = rememberTextFieldState("ABC-DEF-GHI"), isSubmitting = false, snackbarHostState = remember { SnackbarHostState() }, onBackClick = {}, diff --git a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModelTest.kt b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModelTest.kt index 73f74a3feb..c0ac11196d 100644 --- a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModelTest.kt +++ b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/deliveryverification/MasterKeyViewModelTest.kt @@ -37,7 +37,7 @@ class MasterKeyViewModelTest { val viewModel = viewModel(authRepository, receiverRepository) listOf("wrong-key-0000", "1-1-1-1-1").forEach { invalidMasterKey -> - viewModel.submit(senderId = "sender-id", authCode = invalidMasterKey) + viewModel.submit(senderId = "sender-id", masterKey = invalidMasterKey) assertEquals( UiText.Resource(R.string.receiver_verify_master_key_invalid_format), @@ -47,7 +47,7 @@ class MasterKeyViewModelTest { } assertTrue(authRepository.verifiedMasterKeys.isEmpty()) - assertTrue(receiverRepository.savedAuthCodes.isEmpty()) + assertTrue(receiverRepository.savedMasterKeys.isEmpty()) } @Test @@ -59,10 +59,10 @@ class MasterKeyViewModelTest { val masterKey = "123e4567-e89b-12d3-a456-426614174000" val viewModel = viewModel(authRepository, receiverRepository, senderRegistry) - viewModel.submit(senderId = sender.id, authCode = " $masterKey\n") + viewModel.submit(senderId = sender.id, masterKey = " $masterKey\n") assertEquals(listOf(masterKey), authRepository.verifiedMasterKeys) - assertEquals(listOf(masterKey), receiverRepository.savedAuthCodes) + assertEquals(listOf(masterKey), receiverRepository.savedMasterKeys) assertEquals("발신자", senderRegistry.findById(sender.id)?.realSenderName) assertTrue(viewModel.uiState.value.isVerified) assertFalse(viewModel.uiState.value.isSubmitting) @@ -77,11 +77,11 @@ class MasterKeyViewModelTest { val sender = senderRegistry.register("별칭") val viewModel = viewModel(authRepository, receiverRepository, senderRegistry) - viewModel.submit(senderId = sender.id, authCode = "123E4567-E89B-12D3-A456-426614174000") + viewModel.submit(senderId = sender.id, masterKey = "123E4567-E89B-12D3-A456-426614174000") val normalized = "123e4567-e89b-12d3-a456-426614174000" assertEquals(listOf(normalized), authRepository.verifiedMasterKeys) - assertEquals(listOf(normalized), receiverRepository.savedAuthCodes) + assertEquals(listOf(normalized), receiverRepository.savedMasterKeys) assertTrue(viewModel.uiState.value.isVerified) assertEquals(null, viewModel.uiState.value.error) } @@ -105,7 +105,7 @@ class MasterKeyViewModelTest { private fun fakeReceiverRepository(): FakeReceiverRepository = FakeReceiverRepository.strict().apply { - onSaveAuthCode = { code -> authCodeState.value = code } + onSaveMasterKey = { code -> masterKeyState.value = code } } private object NoopErrorReporter : ErrorReporter { diff --git a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailApprovedAtTest.kt b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailApprovedAtTest.kt index ffb70b7a8b..45dcea11e9 100644 --- a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailApprovedAtTest.kt +++ b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailApprovedAtTest.kt @@ -147,7 +147,7 @@ class SenderDetailApprovedAtTest { status: DeliveryVerificationStatus, ) { val registry = SenderRegistry() - val receiver = FakeReceiverRepository.strict().apply { onSaveAuthCode = {} } + val receiver = FakeReceiverRepository.strict().apply { onSaveMasterKey = {} } val auth = FakeReceiverAuthRepository( onGetDeliveryVerificationStatus = { @@ -169,7 +169,7 @@ class SenderDetailApprovedAtTest { val entry = registry.register("아버지") registry.attachIdentity( id = entry.id, - authCode = MY_AUTH_CODE, + masterKey = MY_AUTH_CODE, identity = ReceiverIdentity( receiverId = 1L, @@ -202,11 +202,11 @@ class SenderDetailApprovedAtTest { const val MY_AUTH_CODE = "auth-1" fun recordBox( - accessCode: String, + masterKey: String, approvedAt: String?, ) = ReceivedRecordBox( receiverId = 1L, - accessCode = accessCode, + masterKey = masterKey, senderName = "김발신", verificationStatus = DeliveryVerificationStatus.APPROVED, requestedAt = "2026-06-21T03:07:26", diff --git a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModelTest.kt b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModelTest.kt index 82bb49389f..1e343b97a8 100644 --- a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModelTest.kt +++ b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/senderdetail/SenderDetailViewModelTest.kt @@ -124,7 +124,7 @@ private class Fixture { val statusResults = ArrayDeque>() val receiver = FakeReceiverRepository.strict().apply { - onSaveAuthCode = {} + onSaveMasterKey = {} } val auth = FakeReceiverAuthRepository( @@ -136,7 +136,7 @@ private class Fixture { val entry = registry.register("아버지") registry.attachIdentity( id = entry.id, - authCode = "auth-1", + masterKey = "auth-1", identity = ReceiverIdentity( receiverId = 1L,