7.7 KiB
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.yamldoes not currently register a Windows plugin platform.- There is no
packages/messaging_flutter/windows/plugin scaffold and noapps/flutter-test/windows/host scaffold in the current repository. - Dart already expects native notification and action channels:
com.tokilabs.nexo.messaging/notificationsandcom.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:
- Add a Windows plugin platform registration and generated host scaffold in a controlled implementation plan.
- Register the expected EventChannel and MethodChannel in the Windows plugin.
- Implement a debug-only local injection path compatible with
debugSendNativeEvent. - Choose a notification API path and package identity strategy for the smoke.
- Map notification activation arguments or user data into the Dart
NotificationOpenedEventcontract. - 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:
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.yamlfor platform registration.apps/flutter-test/README.mdand 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_urlandchannel_idare present,root_idis empty andis_crt_enabledis false, so Dart callsonNavigateToChannel. - Thread fixture:
server_urlandroot_idare present andis_crt_enabledis true, so Dart callsonNavigateToThread.
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.jsonapps/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
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.