234 lines
14 KiB
Text
234 lines
14 KiB
Text
<!-- task=m-mattermost-nexo-messaging-alignment plan=1 tag=REVIEW_SMOKE -->
|
|
|
|
# Plan - REVIEW_SMOKE
|
|
|
|
## 이 파일을 읽는 구현 에이전트에게
|
|
|
|
이 계획의 구현 완료는 active `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 내용으로 채우는 것까지 포함한다. 검증 명령을 실행하고 실제 stdout/stderr 또는 redacted 로그 경로를 기록한 뒤 active 파일을 유지한 채 리뷰 준비를 보고한다.
|
|
|
|
외부 Android runner, private secret, 원격 sibling workspace, emulator, Mattermost API가 다시 차단되면 `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 정확한 결정 필요 사항, 근거, 실행한 명령과 출력, 재개 조건을 채우고 멈춘다. 구현 에이전트는 `USER_REVIEW.md`, archive log, `complete.log`를 만들지 않는다.
|
|
|
|
## 배경
|
|
|
|
이 작업은 `USER_REVIEW` stop state에서 재개한다. 사용자가 원격 runner에 직접 동기화하라고 결정했고, 이후 `~/works/nomadcode`, `~/works/nexo`, `~/works/proto-socket`, private inputs, credential asset, emulator가 준비된 것을 확인했다. 남은 일은 원격 Android runner에서 server-generated signed push smoke를 실제로 실행하고 redacted evidence로 milestone 상태를 갱신하는 것이다.
|
|
|
|
## 사용자 리뷰 요청 흐름
|
|
|
|
구현 중 차단점은 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. code-review가 그 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.
|
|
|
|
## 분석 결과
|
|
|
|
### 읽은 파일
|
|
|
|
- `agent-roadmap/current.md`
|
|
- `agent-roadmap/phase/external-integration/PHASE.md`
|
|
- `agent-roadmap/phase/external-integration/milestones/mattermost-nexo-messaging-alignment.md`
|
|
- `agent-task/m-mattermost-nexo-messaging-alignment/user_review_0.log`
|
|
- `agent-task/m-mattermost-nexo-messaging-alignment/plan_cloud_G07_0.log`
|
|
- `agent-task/m-mattermost-nexo-messaging-alignment/code_review_cloud_G07_0.log`
|
|
- `agent-ops/rules/private/rules.md`
|
|
- `docs/test-environments.md`
|
|
- `apps/client/.gitignore`
|
|
- `apps/client/pubspec.yaml`
|
|
- `apps/client/lib/src/integrations/mattermost/mattermost_auth_service.dart`
|
|
- `apps/client/lib/src/integrations/mattermost/mattermost_push_client.dart`
|
|
- `apps/client/lib/src/integrations/mattermost/mattermost_push_plugin_client.dart`
|
|
- `apps/client/lib/src/integrations/mattermost/mattermost_push_host_integration.dart`
|
|
- `apps/client/test/integrations/mattermost_push_host_integration_test.dart`
|
|
- `../nexo/packages/messaging_flutter/lib/src/nexo_messaging_plugin.dart`
|
|
- `../nexo/packages/messaging_flutter/lib/src/notification_opened_event.dart`
|
|
- `../nexo/packages/messaging_flutter/android/src/main/kotlin/com/tokilabs/nexo/messaging/NexoFirebaseMessagingService.kt`
|
|
- `../nexo/packages/messaging_flutter/android/src/main/kotlin/com/tokilabs/nexo/messaging/NexoMessagingPlugin.kt`
|
|
- `../nexo/packages/messaging_flutter/README.md`
|
|
|
|
### 테스트 커버리지 공백
|
|
|
|
- `user_review_0.log:26`의 checkout 부재 blocker는 해소됨. 원격 preflight에서 sibling repo, private input, credential asset, `emulator-5554`, `flutter test`, `flutter analyze --no-fatal-infos`를 확인했다.
|
|
- Real FCM receipt, valid signature, notification display, opened routing, inline reply, dismiss, ACK는 local test로 검증되지 않는다. `docs/test-environments.md:62` 이하의 remote smoke가 필요한 영역이다.
|
|
- Invalid/unsigned negative controls는 direct push-proxy 접근 가능 여부에 의존한다. 접근 불가 시 Evidence Checklist에서 `N/A`로 기록한다.
|
|
|
|
### 심볼 참조
|
|
|
|
- 변경 심볼: 없음.
|
|
- 확인한 관련 심볼: `MattermostPushClient.setAuthToken(..., identifier:)`, `serverId`, `serverIdentifier`, `mattermost_credentials.json`.
|
|
- 현재 call/reference: `mattermost_auth_service.dart`, `mattermost_push_plugin_client.dart`, `mattermost_push_host_integration_test.dart`, `docs/test-environments.md`, `packages/contracts/notes/flutter-core-api-candidates.md`, `../nexo/packages/messaging_flutter`의 Dart/Android 구현.
|
|
|
|
### 분할 판단
|
|
|
|
Split decision policy was evaluated before choosing plan files. Single plan is appropriate because this follow-up is one external smoke/evidence unit: remote readiness, app run, Mattermost trigger, evidence classification, and roadmap note must describe the same run. Splitting setup/run/evidence would make the evidence harder to correlate and would not produce a useful partial `complete.log`.
|
|
|
|
### 범위 결정 근거
|
|
|
|
Do not implement core Mattermost REST message sending here; the trigger uses private smoke inputs only. Do not modify native push implementation under `apps/client/android`; `../nexo/packages/messaging_flutter` remains the owner. Do not commit raw tokens, passwords, FCM tokens, signing keys, push signatures, or raw log files. Do not implement iOS/macOS runtime.
|
|
|
|
### 빌드 등급
|
|
|
|
Build lane: `cloud-G07`. Rationale: this is terminal/external smoke work with SSH, emulator, private inputs, command output redaction, Mattermost server-generated push delivery, and verification trust recovery after a previous environment-blocked FAIL.
|
|
|
|
## 구현 체크리스트
|
|
|
|
- [ ] [REVIEW_SMOKE-1] 원격 Android runner에서 sibling workspace, private inputs, credential asset, emulator, `flutter pub get`, `flutter test`, `flutter analyze --no-fatal-infos`를 재확인하고 실제 출력 또는 redacted 요약을 기록한다.
|
|
- [ ] [REVIEW_SMOKE-2] `flutter run -d emulator-5554 --no-resident`로 앱을 실행해 로그인, signing key 저장, FCM device token 등록 로그를 redaction 상태로 확보한다.
|
|
- [ ] [REVIEW_SMOKE-3] `.env.mattermost.local`의 Mattermost trigger 환경으로 정상 Mattermost post를 생성해 server-generated signed push를 유발하고, logcat/notification evidence를 PASS/PARTIAL/BLOCKED/N/A로 기록한다.
|
|
- [ ] [REVIEW_SMOKE-4] smoke evidence에 따라 `agent-roadmap/phase/external-integration/milestones/mattermost-nexo-messaging-alignment.md`의 `[signed-smoke-refresh]`와 완료 리뷰 후보를 갱신하거나 미충족 항목을 redacted 작업 컨텍스트로 남긴다.
|
|
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
|
|
|
## [REVIEW_SMOKE-1] Remote Readiness Recheck
|
|
|
|
### 문제
|
|
|
|
Previous review failed because `agent-task/m-mattermost-nexo-messaging-alignment/user_review_0.log:26` recorded no usable remote `nomadcode` checkout. The follow-up must prove that blocker is gone before relying on smoke evidence.
|
|
|
|
### 해결 방법
|
|
|
|
Run deterministic remote preflight. Record file existence and permissions only; do not print file contents.
|
|
|
|
### 수정 파일 및 체크리스트
|
|
|
|
- [ ] `CODE_REVIEW-cloud-G07.md` records preflight output.
|
|
- [ ] No raw secret or credential content is pasted.
|
|
|
|
### 테스트 작성
|
|
|
|
테스트 추가 없음. This is remote environment preflight.
|
|
|
|
### 중간 검증
|
|
|
|
```bash
|
|
ssh toki@toki-labs.com 'source ~/.nomadcode-env.sh; set -e; cd ~/works/nomadcode; test -d apps/client; test -d ../nexo/packages/messaging_flutter; test -d ../proto-socket/dart; test -f agent-ops/rules/private/testing-secrets.md; test -f .env.mattermost.local; test -f apps/client/assets/mattermost_credentials.json; stat -f "%Sp %N" agent-ops/rules/private/testing-secrets.md .env.mattermost.local apps/client/assets/mattermost_credentials.json; command -v flutter; command -v adb; adb devices; cd apps/client; flutter pub get; flutter test; flutter analyze --no-fatal-infos'
|
|
```
|
|
|
|
Expected: private files exist with restrictive permissions, `emulator-5554` is listed, `flutter pub get` succeeds, `flutter test` passes, and analyze exits 0 with the known `avoid_print` info only.
|
|
|
|
## [REVIEW_SMOKE-2] App Launch And Auth Handoff
|
|
|
|
### 문제
|
|
|
|
`docs/test-environments.md:122` requires the Android app run to prove Firebase initialization, Mattermost login, signing key storage, and FCM registration before triggering the push. Without this, the server-generated push can fail for setup reasons rather than plugin behavior.
|
|
|
|
### 해결 방법
|
|
|
|
Clear logcat, run the app on the remote emulator, save raw logs only under `/tmp`, and create a redacted log for task evidence.
|
|
|
|
### 수정 파일 및 체크리스트
|
|
|
|
- [ ] Remote app run output is saved under `/tmp`.
|
|
- [ ] `CODE_REVIEW-cloud-G07.md` records only redacted setup evidence.
|
|
- [ ] Required setup lines from `docs/test-environments.md:134` are PASS/PARTIAL/BLOCKED.
|
|
|
|
### 테스트 작성
|
|
|
|
테스트 추가 없음. This is the device smoke setup run.
|
|
|
|
### 중간 검증
|
|
|
|
```bash
|
|
ssh toki@toki-labs.com 'bash -lc '"'"'set -euo pipefail; source ~/.nomadcode-env.sh; cd ~/works/nomadcode/apps/client; adb -s emulator-5554 logcat -c; flutter run -d emulator-5554 --no-resident 2>&1 | tee /tmp/nomadcode-mattermost-run.raw.log; perl -pe "s#https?://[^[:space:]\\\"]+#<redacted-url>#g; s/android_rn-v2:[A-Za-z0-9:_-]+/android_rn-v2:<redacted>/g; s/New FCM token: .*/New FCM token: <redacted>/g; s/(signature=)[^ ,]+/\${1}<redacted>/g; s/[A-Za-z0-9_-]{80,}/<redacted-long>/g" /tmp/nomadcode-mattermost-run.raw.log > /tmp/nomadcode-mattermost-run.redacted.log; grep -E "FirebaseApp initialization successful|MattermostAuth|PushNotification|FCM device token registered" /tmp/nomadcode-mattermost-run.redacted.log || true'"'"''
|
|
```
|
|
|
|
Expected: app launch completes, login/signing-key/device-registration lines are present or any failure is explicit and redacted.
|
|
|
|
## [REVIEW_SMOKE-3] Server-Generated Push And Evidence
|
|
|
|
### 문제
|
|
|
|
`docs/test-environments.md:146` requires a normal Mattermost post so the server and push-proxy generate the signed FCM path. A manually crafted positive push is not valid evidence.
|
|
|
|
### 해결 방법
|
|
|
|
Use only `.env.mattermost.local` on the remote host to create a Mattermost post. Capture redacted logcat and notification evidence. If direct negative-control push-proxy access is unavailable, mark invalid/unsigned drop as `N/A`.
|
|
|
|
### 수정 파일 및 체크리스트
|
|
|
|
- [ ] Mattermost post trigger exits with HTTP 201 or records exact redacted failure.
|
|
- [ ] Redacted logcat includes FCM receipt, signature outcome, ACK, notification event, opened/reply/dismiss evidence where available.
|
|
- [ ] Evidence Checklist uses only PASS, PARTIAL, BLOCKED, or N/A.
|
|
- [ ] Raw signatures, tokens, passwords, URLs, FCM tokens, and raw payloads are not pasted into tracked files.
|
|
|
|
### 테스트 작성
|
|
|
|
테스트 추가 없음. This is the external smoke required by the milestone.
|
|
|
|
### 중간 검증
|
|
|
|
```bash
|
|
ssh toki@toki-labs.com 'bash -s' <<'REMOTE'
|
|
set -euo pipefail
|
|
source ~/.nomadcode-env.sh
|
|
cd ~/works/nomadcode
|
|
set -a
|
|
source .env.mattermost.local
|
|
set +a
|
|
adb -s emulator-5554 logcat -c
|
|
message="nomadcode signed push smoke $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
python3 - "$MATTERMOST_TEST_CHANNEL_ID" "$message" > /tmp/nomadcode-mm-post-body.json <<'PY'
|
|
import json, sys
|
|
print(json.dumps({"channel_id": sys.argv[1], "message": sys.argv[2]}))
|
|
PY
|
|
status=$(curl -sS -o /tmp/nomadcode-mm-post-response.json -w "%{http_code}" \
|
|
-H "Authorization: Bearer ${MATTERMOST_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
--data @/tmp/nomadcode-mm-post-body.json \
|
|
"${MATTERMOST_BASE_URL}/api/v4/posts")
|
|
echo "post-http-status=${status}"
|
|
sleep 15
|
|
adb -s emulator-5554 logcat -d -v time > /tmp/nomadcode-mm-smoke.raw.log
|
|
perl -pe 's#https?://[^[:space:]"]+#<redacted-url>#g; s/android_rn-v2:[A-Za-z0-9:_-]+/android_rn-v2:<redacted>/g; s/New FCM token: .*/New FCM token: <redacted>/g; s/(signature=)[^ ,]+/${1}<redacted>/g; s/[A-Za-z0-9_-]{80,}/<redacted-long>/g' \
|
|
/tmp/nomadcode-mm-smoke.raw.log > /tmp/nomadcode-mm-smoke.redacted.log
|
|
grep -E 'NexoFCM|ReceiptDelivery|Notification skipped|Sending notification event|MattermostHost|PushNotification' /tmp/nomadcode-mm-smoke.redacted.log || true
|
|
adb -s emulator-5554 shell dumpsys notification > /tmp/nomadcode-mm-notification.raw.txt || true
|
|
perl -pe 's#https?://[^[:space:]"]+#<redacted-url>#g; s/android_rn-v2:[A-Za-z0-9:_-]+/android_rn-v2:<redacted>/g; s/[A-Za-z0-9_-]{80,}/<redacted-long>/g' \
|
|
/tmp/nomadcode-mm-notification.raw.txt > /tmp/nomadcode-mm-notification.redacted.txt || true
|
|
REMOTE
|
|
```
|
|
|
|
Expected: `post-http-status=201`; redacted logcat provides enough evidence to classify the checklist at `docs/test-environments.md:213`. If notification interaction requires manual emulator UI, record the exact action and redacted log/dumpsys evidence.
|
|
|
|
## [REVIEW_SMOKE-4] Roadmap Evidence Update
|
|
|
|
### 문제
|
|
|
|
The milestone task at `agent-roadmap/phase/external-integration/milestones/mattermost-nexo-messaging-alignment.md:36` remains unchecked until smoke evidence is recorded. It must not move to `[검토중]` unless the required evidence is actually satisfied.
|
|
|
|
### 해결 방법
|
|
|
|
Update the milestone with a short redacted evidence note. If the evidence checklist passes except optional negative controls/thread navigation, mark `[signed-smoke-refresh]` complete and set completion review to `[검토중]`; otherwise keep `[진행중]`, leave the task unchecked, and record the blocked/partial items.
|
|
|
|
### 수정 파일 및 체크리스트
|
|
|
|
- [ ] `agent-roadmap/phase/external-integration/milestones/mattermost-nexo-messaging-alignment.md` reflects actual evidence.
|
|
- [ ] Evidence note contains no raw private value.
|
|
- [ ] `git diff --check` is clean.
|
|
|
|
### 테스트 작성
|
|
|
|
테스트 추가 없음. This is roadmap evidence documentation.
|
|
|
|
### 중간 검증
|
|
|
|
```bash
|
|
git diff --check
|
|
```
|
|
|
|
Expected: no whitespace errors.
|
|
|
|
## 수정 파일 요약
|
|
|
|
| 파일 | 항목 |
|
|
|------|------|
|
|
| `agent-roadmap/phase/external-integration/milestones/mattermost-nexo-messaging-alignment.md` | REVIEW_SMOKE-4 |
|
|
| `agent-task/m-mattermost-nexo-messaging-alignment/CODE_REVIEW-cloud-G07.md` | REVIEW_SMOKE-1, REVIEW_SMOKE-2, REVIEW_SMOKE-3, REVIEW_SMOKE-4 |
|
|
| remote ignored `~/works/nomadcode/apps/client/assets/mattermost_credentials.json` | REVIEW_SMOKE-1, REVIEW_SMOKE-2 |
|
|
| remote ignored `~/works/nomadcode/.env.mattermost.local` | REVIEW_SMOKE-1, REVIEW_SMOKE-3 |
|
|
|
|
## 최종 검증
|
|
|
|
```bash
|
|
ssh toki@toki-labs.com 'source ~/.nomadcode-env.sh; cd ~/works/nomadcode/apps/client; flutter test'
|
|
ssh toki@toki-labs.com 'source ~/.nomadcode-env.sh; cd ~/works/nomadcode/apps/client; flutter analyze --no-fatal-infos'
|
|
git diff --check
|
|
```
|
|
|
|
Expected: remote Flutter tests pass; remote analyze exits 0 with known `avoid_print` info only; `git diff --check` is clean. All smoke outputs and evidence classification must be pasted into `CODE_REVIEW-cloud-G07.md` with private values redacted or with redacted remote log paths.
|
|
|
|
모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|