<!-- task=mattermost_push_plugin_extraction/03+01,02_host_consumer plan=0 tag=REFACTOR -->

# Host App Plugin Consumer Plan

## 이 파일을 읽는 구현 에이전트에게

구현을 끝내기 전 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 반드시 채운다. 검증 명령을 실제로 실행하고 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 둔 채 review ready를 보고한다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review-skill 전용이다.

## 배경

Native code가 plugin으로 이동한 뒤에도 NomadCode 앱이 기존 local facade와 Android service/helper/resource를 들고 있으면 extraction이 끝나지 않는다. 이 subtask는 `apps/mobile`을 `mattermost_push_plugin` path dependency consumer로 전환하고 앱에는 Firebase project 설정, Mattermost auth flow, workspace UI, notification routing callback만 남긴다. Android manifest와 Gradle dependency ownership도 app에서 plugin으로 넘긴다.

## 분석 결과

### 읽은 파일

- `agent-ops/roadmap/current.md`
- `agent-ops/roadmap/milestones/mattermost-push-plugin-extraction.md`
- `agent-ops/rules/project/domain/mobile/rules.md`
- `apps/mobile/pubspec.yaml`
- `apps/mobile/pubspec.lock`
- `apps/mobile/lib/main.dart`
- `apps/mobile/lib/services/mattermost_auth_service.dart`
- `apps/mobile/lib/services/push_notification_background.dart`
- `apps/mobile/lib/services/push_notification_service.dart`
- `apps/mobile/test/widget_test.dart`
- `apps/mobile/android/app/build.gradle.kts`
- `apps/mobile/android/app/src/main/AndroidManifest.xml`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/MainActivity.kt`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/MainApplication.kt`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/MattermostFirebaseMessagingService.kt`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/NotificationDismissService.java`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/NotificationReplyBroadcastReceiver.java`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/ReceiptDelivery.java`
- `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/helpers/**`

### 테스트 커버리지 공백

- Existing widget tests instantiate `MyApp` and `WorkspaceHomePage`, but they do not verify plugin initialization or channel calls.
- Import migration and dependency cleanup are covered by `flutter test`, `flutter analyze --no-fatal-infos`, and debug Android build.
- Runtime notification tap/inline reply still requires manual smoke criteria documented in `05+03,04_docs_verify`.

### 심볼 참조

- `push_notification_service.dart` is imported by `apps/mobile/lib/main.dart:8` and `apps/mobile/lib/services/mattermost_auth_service.dart:5`.
- `PushNotificationService` is constructed at `apps/mobile/lib/main.dart:13` and typed at `mattermost_auth_service.dart:9`.
- `firebase_messaging` is imported by `main.dart:3` and `push_notification_background.dart:1`; plugin consumer migration should remove host direct use unless another host-owned feature still needs it.
- Android native app entries remain in `AndroidManifest.xml:10`, `58`, `67`, `73` and Gradle dependencies remain in `app/build.gradle.kts:52-71`.

### 분할 판단

- Split decision policy was evaluated before choosing plan files.
- This subtask depends on `01_plugin_api` and `02+01_android_native`; both predecessor directories must have `complete.log` before implementation starts.
- Host migration is split from native move because it deletes app-owned files and changes `pubspec.lock`, which should happen only after plugin native compile is proven.

### 범위 결정 근거

- Do not add new Mattermost auth UI; Milestone excludes Mattermost auth product UI completion.
- Do not complete DB DAO stubs; `04+02_risk_hardening` owns that.
- Do not write final README/smoke docs; `05+03,04_docs_verify` owns docs.
- Do not modify core service or contracts; push extraction is mobile/plugin-boundary work.

### 빌드 등급

- Build lane: `cloud-G07`; review lane: `cloud-G07`. App dependency/import/native ownership cleanup spans Dart, Android manifest, Gradle, generated lockfile, and weak tests.

## 구현 체크리스트

- [ ] [REFACTOR-1] `apps/mobile`에 `mattermost_push_plugin` path dependency를 추가하고 Dart imports/call sites를 plugin API로 전환한다.
- [ ] [REFACTOR-2] app-owned push Dart facade/background handler와 Android native source/resource ownership을 제거한다.
- [ ] [REFACTOR-3] host Android manifest와 Gradle dependencies를 plugin consumer 형태로 정리하고 app 검증을 실행한다.
- [ ] 중간 검증과 최종 검증 명령을 모두 실행하고 실제 출력을 `CODE_REVIEW-cloud-G07.md`에 붙여 넣는다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- Directory dependency: `03+01,02_host_consumer` depends on `01_plugin_api` and `02+01_android_native`.
- Start only after both `agent-task/mattermost_push_plugin_extraction/01_plugin_api/complete.log` and `agent-task/mattermost_push_plugin_extraction/02+01_android_native/complete.log` exist.

### [REFACTOR-1] Dart Consumer Migration

#### 문제

`apps/mobile/lib/main.dart:8` and `mattermost_auth_service.dart:5` import local push service, and `pubspec.yaml:39-48` has no plugin path dependency.

Before (`apps/mobile/pubspec.yaml:39`):

```yaml
  # Firebase
  firebase_core: ^3.13.0
  firebase_messaging: ^15.2.5
```

After:

```yaml
  # Firebase
  firebase_core: ^3.13.0

  # Mattermost push plugin
  mattermost_push_plugin:
    path: ../../../mattermost-push-plugin
```

Before (`apps/mobile/lib/main.dart:6`):

```dart
import 'services/mattermost_auth_service.dart';
import 'services/push_notification_background.dart';
import 'services/push_notification_service.dart';
```

After:

```dart
import 'package:mattermost_push_plugin/mattermost_push_plugin.dart';
import 'services/mattermost_auth_service.dart';
```

#### 해결 방법

Add the path dependency, run `flutter pub get`, update app imports and types from `PushNotificationService` to plugin API. Keep Firebase Core initialization in host app. Remove `FirebaseMessaging.onBackgroundMessage` from host if native plugin service owns Android push handling and no host-owned background handler remains.

#### 수정 파일 및 체크리스트

- [ ] `apps/mobile/pubspec.yaml` path dependency 추가
- [ ] `apps/mobile/pubspec.lock` regenerated by `flutter pub get`
- [ ] `apps/mobile/lib/main.dart` imports and `_pushService` construction update
- [ ] `apps/mobile/lib/services/mattermost_auth_service.dart` import/type update
- [ ] `apps/mobile/test/widget_test.dart` still pumps `MyApp` successfully

#### 테스트 작성

Existing widget tests are enough for app import/bootstrap regression. New plugin API tests are owned by `01_plugin_api`.

#### 중간 검증

```bash
cd /config/workspace/nomadcode/apps/mobile && flutter pub get
```

Expected: path dependency resolves and lockfile updates.

### [REFACTOR-2] Remove App-Owned Push Implementation

#### 문제

After plugin migration, app should not own Mattermost push service/helper/resource files. Current app native files are still under `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/`.

Before (`apps/mobile/android/app/src/main/AndroidManifest.xml:56`):

```xml
        <!-- Firebase Messaging Service (네이티브) -->
        <service
            android:name=".MattermostFirebaseMessagingService"
            android:exported="false">
```

After:

```xml
        <!-- Mattermost push service is provided by mattermost_push_plugin. -->
```

#### 해결 방법

Delete app-local push facade/background handler and native push files after imports are migrated. Keep app `MainActivity` only for Flutter window/system UI concerns and keep `MainApplication` only if the app still has host-owned initialization; otherwise remove the custom `android:name` and class.

#### 수정 파일 및 체크리스트

- [ ] Delete `apps/mobile/lib/services/push_notification_service.dart`
- [ ] Delete `apps/mobile/lib/services/push_notification_background.dart` if unused
- [ ] Delete `MattermostFirebaseMessagingService.kt`, receivers, ACK, lifecycle tracker, helpers, DB files from app source
- [ ] Remove app notification icons/resources only if they are no longer used by host launcher
- [ ] Ensure `rg --sort path "PushNotificationService|push_notification_service" apps/mobile/lib apps/mobile/test` has no matches

#### 테스트 작성

Skip new tests; this is call-site cleanup with existing widget tests and build checks.

#### 중간 검증

```bash
cd /config/workspace/nomadcode && rg --sort path "PushNotificationService|push_notification_service" apps/mobile/lib apps/mobile/test
```

Expected: no output and exit code 1. Record the actual output and exit code.

### [REFACTOR-3] Host Manifest and Gradle Cleanup

#### 문제

Host app still owns Firebase Messaging, JJWT, OkHttp, coroutines, Room/kapt dependencies at `app/build.gradle.kts:52-71`, and manifest entries that should be provided by plugin.

Before (`apps/mobile/android/app/build.gradle.kts:49`):

```kotlin
dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
    implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
    implementation("com.google.firebase:firebase-messaging")
```

After:

```kotlin
dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
}
```

#### 해결 방법

Remove Android native dependencies and `kotlin-kapt` from app if no host app code needs them. Keep `com.google.gms.google-services` because the host app owns Firebase project config. Remove app manifest service/receiver declarations for Mattermost push and only keep plugin conflict overrides if the merged manifest still needs them; otherwise delete stale `tools` namespace usage.

#### 수정 파일 및 체크리스트

- [ ] `apps/mobile/android/app/build.gradle.kts` remove native push dependencies and unused plugin IDs
- [ ] `apps/mobile/android/app/src/main/AndroidManifest.xml` remove app service/receiver registrations
- [ ] `apps/mobile/android/app/src/main/AndroidManifest.xml` keep Firebase config and launcher activity intact
- [ ] `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/MainActivity.kt` no longer registers plugin channels
- [ ] `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/MainApplication.kt` removed or reduced to host-only logic

#### 테스트 작성

Skip new tests; use analyzer, widget tests, and Android debug build.

#### 중간 검증

```bash
cd /config/workspace/nomadcode/apps/mobile && flutter build apk --debug
```

Expected: host app builds with plugin path dependency.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/mobile/pubspec.yaml` | REFACTOR-1 |
| `apps/mobile/pubspec.lock` | REFACTOR-1 |
| `apps/mobile/lib/main.dart` | REFACTOR-1 |
| `apps/mobile/lib/services/mattermost_auth_service.dart` | REFACTOR-1 |
| `apps/mobile/lib/services/push_notification_service.dart` | REFACTOR-2 |
| `apps/mobile/lib/services/push_notification_background.dart` | REFACTOR-2 |
| `apps/mobile/android/app/src/main/java/com/tokilabs/mattermost/**` | REFACTOR-2, REFACTOR-3 |
| `apps/mobile/android/app/src/main/AndroidManifest.xml` | REFACTOR-2, REFACTOR-3 |
| `apps/mobile/android/app/build.gradle.kts` | REFACTOR-3 |
| `apps/mobile/test/widget_test.dart` | REFACTOR-1 |

## 최종 검증

```bash
cd /config/workspace/nomadcode/apps/mobile && flutter pub get
cd /config/workspace/nomadcode/apps/mobile && dart format --output=none --set-exit-if-changed lib test
cd /config/workspace/nomadcode/apps/mobile && flutter analyze --no-fatal-infos
cd /config/workspace/nomadcode/apps/mobile && flutter test
cd /config/workspace/nomadcode/apps/mobile && flutter build apk --debug
cd /config/workspace/nomadcode && rg --sort path "PushNotificationService|push_notification_service|MattermostFirebaseMessagingService|NotificationReplyBroadcastReceiver|NotificationDismissService|ReceiptDelivery|PushNotificationDataHelper" apps/mobile/lib apps/mobile/android/app/src/main/java apps/mobile/test
```

Expected: first five commands succeed. Final `rg` should produce no output and exit code 1; record both output and exit code. Cached Flutter test output is acceptable; Android build must be freshly run.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
