add windows notification docs, update roadmap and flutter test READMEs

This commit is contained in:
toki 2026-06-02 08:04:21 +09:00
parent 0faa687954
commit cc9f99c54a
11 changed files with 327 additions and 20 deletions

View file

@ -12,7 +12,7 @@ macOS native bridge 최소 범위, host placeholder, payload fixture, evidence
## 상태
[검토중]
[완료]
## 승격 조건
@ -46,16 +46,16 @@ Apple signing, 장비, OS UI 수동 검증 전에 먼저 확정할 수 있는
## 완료 리뷰
- 상태: 요청
- 상태: 승인
- 요청일: 2026-06-02
- 완료 근거:
- `docs/macos-notification-test-guide.md`에 macOS bridge scope, host placeholder, userInfo mapping, fixture 사용 기준을 정리했다.
- `apps/flutter-test/macos/Fixtures/*.json`에 channel/thread open routing fixture를 추가했다.
- `docs/macos-notification-smoke-evidence-template.md`에 permission, display, click/open routing, lifecycle, ACK/dismiss/inline reply gap evidence 양식을 추가했다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 모든 기능 Task가 문서/fixture/evidence 기준으로 충족되어 완료 후보로 올린다. 실제 macOS native bridge 구현과 OS notification UI smoke는 후속 Milestone 또는 별도 plan 대상이다.
- [x] 사용자가 완료 결과를 확인했다
- [x] archive 이동을 승인했다
- 리뷰 코멘트: 사용자가 완료와 다음 마일스톤 지점 업데이트를 요청했다. 실제 macOS native bridge 구현과 OS notification UI smoke는 후속 Milestone 또는 별도 plan 대상이다.
## 범위 제외

View file

@ -7,9 +7,9 @@
## 활성 Milestone
- [검토중] macOS 알림 선행 정리
- [검토중] Windows 알림 선행 정리
- Phase: `agent-roadmap/phase/messaging-runtime/PHASE.md`
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/macos-notification-preflight.md`
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/windows-notification-preflight.md`
## 선택 규칙

View file

@ -25,10 +25,10 @@ Mattermost server/webapp/push-proxy는 upstream-followable runtime으로 두고,
- [완료] iOS 알림 선행 정리
- 경로: `agent-roadmap/archive/phase/messaging-runtime/milestones/ios-notification-preflight.md`
- 요약: Apple/Firebase/APNs 실자산 없이 iOS token 계약, native bridge 최소 범위, fixture, evidence 기준을 정리했다.
- [검토중] macOS 알림 선행 정리
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/macos-notification-preflight.md`
- [완료] macOS 알림 선행 정리
- 경로: `agent-roadmap/archive/phase/messaging-runtime/milestones/macos-notification-preflight.md`
- 요약: Apple signing/장비 없이 macOS native bridge 최소 범위, host placeholder, fixture, evidence 기준을 먼저 정리한다.
- [계획] Windows 알림 선행 정리
- [검토중] Windows 알림 선행 정리
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/windows-notification-preflight.md`
- 요약: Windows 장비/packaging 결정 없이 plugin 등록, native API 후보, bridge 계약, fixture, evidence 기준을 먼저 정리한다.
- [계획] Linux 알림 선행 정리

View file

@ -12,7 +12,7 @@ Windows plugin 등록, native notification API 후보, bridge 계약, fixture, e
## 상태
[계획]
[검토중]
## 승격 조건
@ -38,21 +38,24 @@ Windows plugin 등록, native notification API 후보, bridge 계약, fixture, e
Windows 장비, 계정, packaging 결정을 기다리지 않고 먼저 확정할 수 있는 계약과 검증 표면을 분리한다.
- [ ] [platform-contract] Windows plugin 등록 방식, Dart channel 이름, host scaffold 필요 범위를 정리한다.
- [ ] [bridge-scope] Windows native notification open event를 `NotificationOpenedEvent`와 channel/thread callback에 연결하는 최소 bridge 계약을 정리한다.
- [ ] [api-matrix] Windows notification API 후보와 app packaging/MSIX 여부에 따른 제약을 비교한다.
- [ ] [fixtures] local/debug notification payload fixture와 opened-routing injection 시나리오를 작성한다.
- [ ] [evidence-template] display, click/open routing, lifecycle, ACK/dismiss gap evidence 템플릿을 작성한다.
- [x] [platform-contract] Windows plugin 등록 방식, Dart channel 이름, host scaffold 필요 범위를 정리한다.
- [x] [bridge-scope] Windows native notification open event를 `NotificationOpenedEvent`와 channel/thread callback에 연결하는 최소 bridge 계약을 정리한다.
- [x] [api-matrix] Windows notification API 후보와 app packaging/MSIX 여부에 따른 제약을 비교한다.
- [x] [fixtures] local/debug notification payload fixture와 opened-routing injection 시나리오를 작성한다.
- [x] [evidence-template] display, click/open routing, lifecycle, ACK/dismiss gap evidence 템플릿을 작성한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 상태: 요청됨
- 요청일: 2026-06-02
- 완료 근거:
- `docs/windows-notification-test-guide.md`에 Windows platform registration, bridge scope, API matrix, payload mapping, fixture 사용 기준을 정리했다.
- `apps/flutter-test/windows/Fixtures/*.json`에 channel/thread open routing fixture를 추가했다.
- `docs/windows-notification-smoke-evidence-template.md`에 display, click/open routing, lifecycle, ACK/dismiss/inline reply gap evidence 양식을 추가했다.
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
- 리뷰 코멘트: 모든 기능 Task가 문서/fixture/evidence 기준으로 충족되어 완료 후보로 올린다. 실제 Windows plugin scaffold, platform registration, native bridge 구현과 OS notification UI smoke는 후속 Milestone 또는 별도 plan 대상이다.
## 범위 제외

View file

@ -94,6 +94,16 @@ routing fixtures live under `macos/Fixtures/*.json`. See
and
[`../../docs/macos-notification-smoke-evidence-template.md`](../../docs/macos-notification-smoke-evidence-template.md).
For Windows preflight and smoke preparation, keep real Microsoft account,
package identity, signing, push credentials, device token, and private host
values out of git. This repository does not currently include a Windows host
scaffold; add one only through a focused implementation plan that also registers
the plugin platform. Local routing fixtures live under
`windows/Fixtures/*.json`. See
[`../../docs/windows-notification-test-guide.md`](../../docs/windows-notification-test-guide.md)
and
[`../../docs/windows-notification-smoke-evidence-template.md`](../../docs/windows-notification-smoke-evidence-template.md).
## Verification
The integration test uses the plugin's test/debug event injection path for

View file

@ -0,0 +1,11 @@
{
"type": "message",
"server_url": "https://example.invalid",
"server_id": "server-smoke",
"channel_id": "channel-smoke",
"root_id": "",
"is_crt_enabled": "false",
"ack_id": "ack-smoke-channel",
"post_id": "post-smoke-channel",
"userInteraction": true
}

View file

@ -0,0 +1,11 @@
{
"type": "message",
"server_url": "https://example.invalid",
"server_id": "server-smoke",
"channel_id": "channel-smoke",
"root_id": "thread-smoke",
"is_crt_enabled": "true",
"ack_id": "ack-smoke-thread",
"post_id": "post-smoke-thread",
"userInteraction": true
}

View file

@ -16,6 +16,10 @@ Module-specific instructions stay with the module that owns them.
- Runtime Image Validation details: `runtime-image-validation.md`
- iOS notification smoke prerequisites and runbook: `ios-notification-test-guide.md`
- iOS notification smoke evidence template: `ios-notification-smoke-evidence-template.md`
- macOS notification smoke prerequisites and runbook: `macos-notification-test-guide.md`
- macOS notification smoke evidence template: `macos-notification-smoke-evidence-template.md`
- Windows notification smoke prerequisites and runbook: `windows-notification-test-guide.md`
- Windows notification smoke evidence template: `windows-notification-smoke-evidence-template.md`
## Upstream Following Policy

View file

@ -0,0 +1,95 @@
# Windows Notification Smoke Evidence Template
Use this template when collecting Windows notification smoke evidence. Replace
every private value with a placeholder before storing output in tracked files.
## Run Metadata
- Date:
- Operator:
- Hardware or VM:
- Windows version:
- Visual Studio version:
- Windows SDK version:
- Flutter version:
- Build mode: Debug | Profile | Release
- Packaging mode: unpackaged | MSIX | sparse package | not tested
- Package identity/AppUserModelID: `<redacted-or-placeholder>`
- Notification API path: Windows App SDK | WinRT toast | debug injection | other
## Preflight Inputs
- Windows platform registered in `packages/messaging_flutter/pubspec.yaml`: yes | no
- Windows plugin scaffold present: yes | no
- Windows test host scaffold present: yes | no
- Windows bridge registers `com.tokilabs.nexo.messaging/notifications`: yes | no
- Windows bridge registers `com.tokilabs.nexo.messaging/notification_actions`: yes | no
- Local fixture used: `open_channel.json` | `open_thread.json` | other
- Real account, package, signing, and private host values kept out of tracked files: yes | no
## Display Evidence
Payload file or sanitized JSON:
```json
{
"type": "message",
"server_url": "https://example.invalid",
"server_id": "server-smoke",
"channel_id": "channel-smoke",
"root_id": "",
"is_crt_enabled": "false",
"ack_id": "ack-smoke",
"post_id": "post-smoke"
}
```
Display path:
- Local debug injection:
- Windows App SDK notification:
- WinRT toast notification:
- Not tested:
Observed result:
```text
displayed=<yes|no|not_implemented>
notification_title=<redacted-or-placeholder>
notification_body=<redacted-or-placeholder>
activation_arguments_present=<yes|no|not_implemented>
```
## Click / Open Routing
| Scenario | Expected | Actual | Evidence path |
|---|---|---|---|
| Channel click | `onNavigateToChannel` with server/channel | | |
| Thread click | `onNavigateToThread` with server/root | | |
| Foreground receipt | Raw `onNotification` event logged | | |
| Background click | App resumes and emits opened event | | |
| Cold start click | Launch payload forwarded | | |
## Lifecycle Evidence
```text
app_state_before=<foreground|background|not_running|not_tested>
app_state_after=<foreground|background|not_running|not_tested>
event_type=<message|opened|not_implemented>
userInteraction=<true|false|not_set>
```
## ACK, Dismiss, Inline Reply Boundary
| Feature | Expected for this run | Actual | Follow-up |
|---|---|---|---|
| ACK | gap documented unless implemented by a later plan | | |
| Dismiss | gap documented unless implemented by a later plan | | |
| Inline reply | gap documented unless implemented by a later plan | | |
## Sanitization Checklist
- [ ] Microsoft account, package identity, certificate, Store association, and AppUserModelID values removed.
- [ ] Full device token or remote push token removed.
- [ ] Private server URL, auth token, signing key, username, channel names removed.
- [ ] Screenshots or recordings contain no private message/user data.

View file

@ -0,0 +1,155 @@
# Windows Notification Test Guide
Last verified: 2026-06-02
This guide fixes the preflight contract for Windows notification work before a
Windows test machine, Microsoft account, packaging decision, or real OS
notification UI evidence is available.
Do not commit Microsoft account values, package identity values, signing
certificates, store association files, push credentials, device tokens, auth
tokens, private endpoints, or private host values into tracked docs. Use
placeholders in examples and keep credential files in approved local or
secret-store locations.
## Current Repository State
- `packages/messaging_flutter/pubspec.yaml` does not currently register a
Windows plugin platform.
- There is no `packages/messaging_flutter/windows/` plugin scaffold and no
`apps/flutter-test/windows/` host scaffold in the current repository.
- Dart already expects native notification and action channels:
`com.tokilabs.nexo.messaging/notifications` and
`com.tokilabs.nexo.messaging/notification_actions`.
- The Windows bridge is therefore not implemented yet. Until it exists, local
routing can only be tested through Dart unit tests or a future debug injection
bridge.
- Local routing fixtures live under `apps/flutter-test/windows/Fixtures/*.json`.
The first useful Windows smoke target is:
1. Add a Windows plugin platform registration and generated host scaffold in a
controlled implementation plan.
2. Register the expected EventChannel and MethodChannel in the Windows plugin.
3. Implement a debug-only local injection path compatible with
`debugSendNativeEvent`.
4. Choose a notification API path and package identity strategy for the smoke.
5. Map notification activation arguments or user data into the Dart
`NotificationOpenedEvent` contract.
6. Collect display, click/open routing, lifecycle, and known ACK, dismiss, and
inline reply gap evidence.
## Platform Registration Contract
Do not add a partial Windows platform entry without the matching source and host
scaffold. A future implementation plan should update these together:
```yaml
flutter:
plugin:
platforms:
windows:
pluginClass: NexoMessagingPlugin
```
Expected source/host areas for that plan:
- `packages/messaging_flutter/windows/` for the Windows plugin implementation.
- `apps/flutter-test/windows/` for the test host scaffold generated by Flutter.
- `packages/messaging_flutter/pubspec.yaml` for platform registration.
- `apps/flutter-test/README.md` and package docs for smoke instructions.
The current preflight milestone documents this contract only. It does not claim
Windows runtime support.
## Minimum Bridge Contract
The Dart SDK expects the Windows native side to preserve these channel names:
| Channel | Name | Direction | Minimum Windows behavior |
|---|---|---|---|
| EventChannel | `com.tokilabs.nexo.messaging/notifications` | native to Dart | Emit codec-safe maps for notification, open, token, clear, session, and future action-failure events. |
| MethodChannel | `com.tokilabs.nexo.messaging/notification_actions` | Dart to native | Accept SDK action methods used by Dart without crashing the host app. |
Minimum methods for the action channel:
| Method | Minimum preflight result | Production expectation |
|---|---|---|
| `debugSendNativeEvent` | Validate the argument is a map and emit it on the EventChannel. | Debug/test-only injection path. |
| `saveDeviceToken` | Accept and store or no-op a formatted token string without logging secrets. | Store the Windows server-registration token once the platform token source is chosen. |
| `getDeviceToken` | Return the last stored formatted token or null. | Return the current formatted Windows server-registration token. |
| `setAuthToken` | Validate required string arguments and no-op. | Persist token for ACK/reply work only after storage rules are designed. |
| `clearAuthToken` | Validate `serverUrl` and no-op. | Clear persisted token for the server. |
| `setSigningKey` | Validate required string arguments and no-op without persistence. | Persist the signing key only after secure storage rules are designed. |
Fallback boundaries:
- Missing bridge methods should return the Flutter Windows equivalent of
"not implemented", not a successful placeholder.
- Token, auth, signing-key, ACK, dismiss, and inline reply persistence are not
implied by this preflight milestone.
- Real notification display and activation handling belong to `Windows 알림 테스트`
unless a smaller bridge implementation plan explicitly handles them first.
## Notification API Matrix
| Candidate | Packaging fit | Strength | Preflight constraint |
|---|---|---|---|
| Windows App SDK notifications | Best with package identity or sparse package | Modern toast activation path and current Microsoft guidance | Requires Windows App SDK dependency and packaging decision. |
| WinRT toast notifications | Best with MSIX/package identity | Direct OS toast APIs and activation arguments | Packaging/AppUserModelID details must be decided before reliable smoke. |
| Desktop bridge / AppUserModelID shortcuts | Unpackaged desktop fallback | Can support classic desktop notification experiments | More local setup variance and weaker repeatability. |
| Local debug injection only | No packaging requirement | Deterministic EventChannel/opened-routing verification | Does not prove OS display or activation. |
Preflight default: use local debug injection for contract tests, and defer the
Windows App SDK vs WinRT packaging decision to the `Windows 알림 테스트` milestone
or a dedicated implementation plan.
## Payload Mapping
Windows activation payloads map into Dart using the same stable keys as the
Android, iOS, and macOS contracts:
| Payload key | Dart event field | Notes |
|---|---|---|
| `type` | `type` | Use `message` for visible message notifications and `opened` for direct open events. |
| `server_url` | `server_url` | Required before host navigation callbacks can run. |
| `server_id` | `server_id` | Diagnostic and future server URL fallback input. |
| `channel_id` | `channel_id` | Drives `onNavigateToChannel` when thread routing is not selected. |
| `root_id` | `root_id` | Drives `onNavigateToThread` when CRT is enabled. |
| `is_crt_enabled` | `is_crt_enabled` | Accept boolean `true`, string `"true"`, or string `"1"`. |
| `ack_id` | `ack_id` | Preserve for future ACK evidence; do not invent ACK behavior. |
| `post_id` | `post_id` | Preserve for notification identity and future ACK/display evidence. |
| `userInteraction` | `userInteraction` | Set to `true` when a click/open path caused the event. |
Routing expectation:
- Channel fixture: `server_url` and `channel_id` are present, `root_id` is empty
and `is_crt_enabled` is false, so Dart calls `onNavigateToChannel`.
- Thread fixture: `server_url` and `root_id` are present and
`is_crt_enabled` is true, so Dart calls `onNavigateToThread`.
## Local Fixtures
Use the fixture files as sanitized payloads for a future debug injection method
or for manual activation/user-data construction during smoke testing:
- `apps/flutter-test/windows/Fixtures/open_channel.json`
- `apps/flutter-test/windows/Fixtures/open_thread.json`
The fixtures intentionally use `https://example.invalid` and smoke IDs. Replace
private runtime values only in local run notes or sanitized evidence.
## Evidence
Use [`windows-notification-smoke-evidence-template.md`](windows-notification-smoke-evidence-template.md)
for Windows runs. Preflight evidence should explicitly separate:
- packaging and identity state
- visible display state
- click/open routing result
- app lifecycle state
- ACK, dismiss, and inline reply implementation gaps
Until the scaffold, bridge, and real OS smoke exist, a valid preflight result
may be "not implemented yet" with a concrete follow-up plan, rather than a
failed runtime claim.

View file

@ -52,6 +52,7 @@ copying upstream mobile code.
| Android | Production target | Native FCM service, Room storage, JJWT verification, OkHttp ACK client, notification builder, inline reply receiver, dismiss receiver |
| iOS | Stub | Plugin scaffold exists, behavior is not implemented yet |
| macOS | Stub | Plugin scaffold exists; preflight bridge, fixture, host placeholder, and evidence criteria are documented in [`../../docs/macos-notification-test-guide.md`](../../docs/macos-notification-test-guide.md) |
| Windows | Not registered | No Flutter plugin scaffold yet; platform registration, bridge scope, API matrix, fixture, and evidence criteria are documented in [`../../docs/windows-notification-test-guide.md`](../../docs/windows-notification-test-guide.md) |
## Repository Layout
@ -61,6 +62,7 @@ packages/messaging_flutter/
android/ # Android native plugin implementation
ios/ # iOS plugin scaffold
macos/ # macOS plugin scaffold
# windows/ # Not registered yet; see Windows preflight docs
test/ # Dart unit tests for the plugin contract
../../apps/flutter-test/ # Flutter test host
```
@ -517,6 +519,22 @@ Use [`../../docs/macos-notification-test-guide.md`](../../docs/macos-notificatio
for the bridge scope, no-op/fallback boundaries, host placeholder criteria,
payload mapping, fixture paths, and evidence expectations.
## Windows Preflight Notes
Windows is not registered in `pubspec.yaml` and has no plugin scaffold yet. Do
not add a partial Windows platform entry without a matching implementation plan
that creates the plugin source, test host scaffold, channel registration, and
debug injection path together.
Dart still expects any future Windows bridge to use
`com.tokilabs.nexo.messaging/notifications` and
`com.tokilabs.nexo.messaging/notification_actions`, then map toast activation
or debug injection payloads to `NotificationOpenedEvent`.
Use [`../../docs/windows-notification-test-guide.md`](../../docs/windows-notification-test-guide.md)
for platform registration scope, bridge boundaries, notification API candidates,
fixture paths, and evidence expectations.
## Test Strategy
Use deterministic tests for repository-owned behavior. The example integration