update roadmap and README files
This commit is contained in:
parent
625a50bcc9
commit
2904ee663c
5 changed files with 156 additions and 15 deletions
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
## 활성 Milestone
|
||||
|
||||
- [진행중] 메시징 계약 표준화
|
||||
- [검토중] 메시징 계약 표준화
|
||||
- Phase: `agent-roadmap/phase/messaging-runtime/PHASE.md`
|
||||
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/messaging-contract.md`
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Mattermost server/webapp/push-proxy는 upstream-followable runtime으로 두고,
|
|||
완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
|
||||
스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다.
|
||||
|
||||
- [진행중] 메시징 계약 표준화
|
||||
- [검토중] 메시징 계약 표준화
|
||||
- 경로: `agent-roadmap/phase/messaging-runtime/milestones/messaging-contract.md`
|
||||
- 요약: 서버와 Flutter 플러그인이 공유할 메시징/알림 API, 이벤트, 저장 계약을 정리한다.
|
||||
- [계획] 알림 파이프라인 고도화
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ upstream-followable server/push runtime과 nexo-owned Flutter SDK가 주고받
|
|||
|
||||
## 상태
|
||||
|
||||
[진행중]
|
||||
[검토중]
|
||||
|
||||
## 승격 조건
|
||||
|
||||
|
|
@ -41,28 +41,32 @@ upstream-followable server/push runtime과 nexo-owned Flutter SDK가 주고받
|
|||
앱이 의존할 수 있는 최소 메시징/알림 API 표면을 정리한다.
|
||||
|
||||
- [x] [dart-api] Dart public API에서 유지할 이름, deprecated 후보, nexo wrapper 후보를 분리한다.
|
||||
- [ ] [event-shape] notification event, opened event, token event의 payload shape와 backward compatibility 기준을 문서화한다.
|
||||
- [ ] [token-flow] device token 저장, auth token 저장, signing key 저장 책임과 호출 순서를 정리한다.
|
||||
- [ ] [sdk-runtime-boundary] Flutter SDK가 server/push contract를 추적하되 Mattermost mobile implementation을 팔로잉하지 않는 경계를 문서화한다.
|
||||
- [x] [event-shape] notification event, opened event, token event의 payload shape와 backward compatibility 기준을 문서화한다.
|
||||
- [x] [token-flow] device token 저장, auth token 저장, signing key 저장 책임과 호출 순서를 정리한다.
|
||||
- [x] [sdk-runtime-boundary] Flutter SDK가 server/push contract를 추적하되 Mattermost mobile implementation을 팔로잉하지 않는 경계를 문서화한다.
|
||||
|
||||
### Epic: [server-contract] Server contract
|
||||
|
||||
서버 core와 플러그인이 공유하는 메시징/알림 계약을 확인 가능한 형태로 만든다.
|
||||
|
||||
- [ ] [push-payload] push payload 필드와 검증 기준을 서버/플러그인 양쪽 문서에서 연결한다.
|
||||
- [ ] [ack-contract] ACK 요청 형식과 실패 처리 기준을 정리한다.
|
||||
- [ ] [routing-contract] channel/thread navigation event가 client router로 전달되는 기준을 정리한다.
|
||||
- [ ] [front-compat] Mattermost webapp/reference front에서 동작하는 기본 메시징 기능과 Flutter SDK embedded 흐름이 충돌하지 않는 기준을 정리한다.
|
||||
- [x] [push-payload] push payload 필드와 검증 기준을 서버/플러그인 양쪽 문서에서 연결한다.
|
||||
- [x] [ack-contract] ACK 요청 형식과 실패 처리 기준을 정리한다.
|
||||
- [x] [routing-contract] channel/thread navigation event가 client router로 전달되는 기준을 정리한다.
|
||||
- [x] [front-compat] Mattermost webapp/reference front에서 동작하는 기본 메시징 기능과 Flutter SDK embedded 흐름이 충돌하지 않는 기준을 정리한다.
|
||||
|
||||
## 완료 리뷰
|
||||
|
||||
- 상태: 없음
|
||||
- 요청일: 없음
|
||||
- 완료 근거: 없음
|
||||
- 상태: 요청됨
|
||||
- 요청일: 2026-05-30
|
||||
- 완료 근거:
|
||||
- `packages/messaging_flutter/README.md`에 plugin-side public API, event shape, token/credential flow, push payload, ACK, routing, reference front compatibility 기준을 정리했다.
|
||||
- `services/core/compose/README.md`에 server-side source anchors, payload fields, ACK endpoint, webapp/reference front compatibility 기준을 연결했다.
|
||||
- 모든 기능 Task가 문서/테스트/source anchor 근거와 함께 완료 후보가 되었다.
|
||||
- 리뷰 필요:
|
||||
- [ ] 사용자가 완료 결과를 확인했다
|
||||
- [ ] Flutter 앱 우선 노출 범위가 현재 Public API Contract 기준으로 충분한지 확인했다
|
||||
- [ ] archive 이동을 승인했다
|
||||
- 리뷰 코멘트: 없음
|
||||
- 리뷰 코멘트: 모든 기능 Task는 완료 후보이며, 남은 판단은 사용자 최종 확인과 archive 승인이다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
|
|
@ -74,7 +78,10 @@ upstream-followable server/push runtime과 nexo-owned Flutter SDK가 주고받
|
|||
|
||||
- 관련 경로: `packages/messaging_flutter/lib/`, `packages/messaging_flutter/android/`, `services/core/server/`, `services/core/webapp/`, `services/core/compose/`, `apps/flutter-test/`
|
||||
- 표준선(선택): SDK public API는 nexo-owned wrapper로 유지하고, server/webapp/push-proxy compatibility는 얇은 layer로 흡수한다
|
||||
- 진행 근거: 2026-05-30 `packages/messaging_flutter/README.md`에 Public API Contract 섹션을 추가해 유지 API, compatibility/deprecated 후보, nexo wrapper 후보를 분리했다.
|
||||
- 진행 근거:
|
||||
- 2026-05-30 `packages/messaging_flutter/README.md`에 Public API Contract 섹션을 추가해 유지 API, compatibility/deprecated 후보, nexo wrapper 후보를 분리했다.
|
||||
- 2026-05-30 `packages/messaging_flutter/README.md`의 Event Shape Contract, Token And Credential Flow, SDK Ownership Boundary, Runtime Tracking Boundary 섹션과 `packages/messaging_flutter/test/nexo_messaging_test.dart` 근거로 event shape, token flow, SDK/runtime boundary, routing contract를 완료로 판정했다.
|
||||
- 2026-05-30 `packages/messaging_flutter/README.md`와 `services/core/compose/README.md`를 상호 연결해 push payload, ACK, reference front compatibility 계약 기준을 완료 후보로 정리했다.
|
||||
- 선행 작업: 정체성 기준선, 업스트림 팔로잉 기준선, 클라이언트 검증 기준선
|
||||
- 후속 작업: 알림 파이프라인 고도화, 멀티앱 채널 모델
|
||||
- 확인 필요: Flutter 앱 우선 노출 범위
|
||||
|
|
|
|||
|
|
@ -278,6 +278,104 @@ The Dart API currently recognizes these native event types:
|
|||
`onNavigateToThread`; otherwise it calls `onNavigateToChannel` when a channel is
|
||||
available.
|
||||
|
||||
## Server And Push Runtime Contract
|
||||
|
||||
This package consumes the Mattermost-compatible push runtime documented from the
|
||||
server side in
|
||||
[`services/core/compose/README.md`](../../services/core/compose/README.md#sdk-contract-anchors).
|
||||
The plugin keeps compatibility with those fields, while typed app-facing API
|
||||
stays in the Dart surface above.
|
||||
|
||||
### Push Payload Fields
|
||||
|
||||
Server-side source anchor:
|
||||
`services/core/server/public/model/push_notification.go`.
|
||||
|
||||
Plugin-side source anchors:
|
||||
`android/src/main/kotlin/com/tokilabs/nexo/messaging/NexoFirebaseMessagingService.kt`,
|
||||
`android/src/main/java/com/tokilabs/nexo/messaging/helpers/CustomPushNotificationHelper.java`,
|
||||
and `android/src/main/kotlin/com/tokilabs/nexo/messaging/LaunchIntentHelper.kt`.
|
||||
|
||||
| Field | Required for | Plugin handling |
|
||||
| --- | --- | --- |
|
||||
| `type` | Message, clear, session dispatch | Must match the native `PushNotificationType` constants. Unknown types are forwarded only as raw compatibility events. |
|
||||
| `ack_id` | ACK and signature validation | Sent back to `/api/v4/notifications/ack` and required by signed push JWT validation when a signature is present. |
|
||||
| `server_url` | ACK/reply delivery, signature lookup, routing | Preferred server identity. If omitted, Android may resolve it from `server_id` or the single stored server URL. |
|
||||
| `server_id` | Server URL fallback | Resolved through the identifier stored by `setAuthToken(serverUrl, token, identifier: ...)`. |
|
||||
| `channel_id` | Notification grouping and channel routing | Used for notification grouping, clear handling, and `onNavigateToChannel`. |
|
||||
| `root_id` | CRT/thread routing | When CRT is enabled, this groups thread notifications and drives `onNavigateToThread`. |
|
||||
| `is_crt_enabled` | Thread behavior | The string value `"true"` enables thread routing; other values are treated as false. |
|
||||
| `post_id` | ACK id-loaded response and notification identity | Included in ACK requests and used as the Android notification id source. |
|
||||
| `signature` | Payload verification | Verified against the server signing key and stored device token. Missing signatures are accepted for backward compatibility. |
|
||||
| `id_loaded` | ACK response enrichment | The string value `"true"` asks the server to return post data that Android can merge into the notification bundle. |
|
||||
| `category` | Inline reply affordance | `CAN_REPLY` enables the Android inline reply action when `post_id` and `server_url` are present. |
|
||||
|
||||
Validation criteria:
|
||||
|
||||
- A signed payload passes only when the JWT contains the expected `ack_id` and
|
||||
raw device token, and the signing key resolves from the server database or the
|
||||
`setSigningKey()` fallback.
|
||||
- A payload without `server_url` is valid only when `server_id` or the one-server
|
||||
fallback resolves to a server URL before ACK, reply, or signature lookup.
|
||||
- Payload fields not listed here may pass through raw `onNotification` maps for
|
||||
diagnostics, but consuming apps should not treat them as stable API.
|
||||
|
||||
### ACK Contract
|
||||
|
||||
Plugin-side source anchor:
|
||||
`android/src/main/java/com/tokilabs/nexo/messaging/ReceiptDelivery.java`.
|
||||
|
||||
Server-side source anchors:
|
||||
`services/core/server/public/model/push_notification.go` and
|
||||
`services/core/server/channels/api4/system.go`.
|
||||
|
||||
The plugin POSTs ACKs to `/api/v4/notifications/ack` with:
|
||||
|
||||
| Request field | Value |
|
||||
| --- | --- |
|
||||
| `id` | Push payload `ack_id`. |
|
||||
| `received_at` | Client receipt timestamp in milliseconds. |
|
||||
| `platform` | `android`. |
|
||||
| `type` | Push payload `type`. |
|
||||
| `post_id` | Push payload `post_id`, when present. |
|
||||
| `is_id_loaded` | Boolean derived from payload `id_loaded == "true"`. |
|
||||
|
||||
The server returns `OK` for ordinary ACKs. When `is_id_loaded` is true and the
|
||||
ACK references a message post, the server may return message fields such as
|
||||
`post_id`, `root_id`, `category`, `message`, `team_id`, `channel_id`,
|
||||
`channel_name`, `type`, `sender_id`, `sender_name`, and `version`; Android merges
|
||||
those fields into the notification bundle before rendering.
|
||||
|
||||
Failure handling criteria:
|
||||
|
||||
- If ACK delivery fails, Android logs the failure and continues signature
|
||||
validation and notification processing with the original payload.
|
||||
- If an id-loaded ACK response cannot be parsed, Android treats it as absent and
|
||||
continues with the original payload.
|
||||
- If the server rejects the ACK because push notifications are disabled,
|
||||
unauthenticated, or the post is unavailable, that is a runtime/server state
|
||||
failure, not a Dart API contract change.
|
||||
|
||||
### Reference Front Compatibility
|
||||
|
||||
The Mattermost webapp under `services/core/webapp` remains the reference front
|
||||
for browser messaging features such as posts, replies, post acknowledgements,
|
||||
channel navigation, and thread state. The Flutter SDK embedded flow must not
|
||||
replace or fork that webapp behavior inside this repository.
|
||||
|
||||
Compatibility criteria:
|
||||
|
||||
- Webapp routes, Redux state, and product UI stay upstream-followable in
|
||||
`services/core/webapp`.
|
||||
- Flutter consuming apps own their own screens and routers; this plugin emits
|
||||
opened events and optional channel/thread callbacks only.
|
||||
- Server compatibility belongs to push payload fields, ACK/reply endpoints,
|
||||
signing-key verification, and device-token format, not to Mattermost mobile or
|
||||
webapp UI implementation details.
|
||||
- If a future Flutter app needs product UI parity with the reference webapp, that
|
||||
work belongs in the consuming app or a separate roadmap item, not in this
|
||||
plugin contract milestone.
|
||||
|
||||
## Android Notes
|
||||
|
||||
The Android manifest declares the plugin's own
|
||||
|
|
|
|||
|
|
@ -59,6 +59,42 @@ docker compose config | rg --fixed-strings \
|
|||
FCM/APNS credential validation is not part of the default smoke. Run it only
|
||||
when a real push-proxy config is present outside git.
|
||||
|
||||
## SDK Contract Anchors
|
||||
|
||||
The Flutter SDK side of this contract is documented in
|
||||
[`packages/messaging_flutter/README.md`](../../../packages/messaging_flutter/README.md#server-and-push-runtime-contract).
|
||||
This compose runtime keeps the Mattermost-compatible server and push-proxy shape
|
||||
that the SDK consumes.
|
||||
|
||||
Server source anchors:
|
||||
|
||||
- Push payload model: `services/core/server/public/model/push_notification.go`
|
||||
- ACK endpoint route and handler: `services/core/server/channels/api4/system.go`
|
||||
- Push signing and push-proxy dispatch: `services/core/server/channels/app/notification_push.go`
|
||||
- Reference webapp client behavior: `services/core/webapp/platform/client/src/client4.ts`,
|
||||
`services/core/webapp/platform/client/src/websocket.ts`, and
|
||||
`services/core/webapp/channels/src/`
|
||||
|
||||
SDK-facing payload fields are `type`, `ack_id`, `server_id`, `device_id`,
|
||||
`post_id`, `category`, `team_id`, `channel_id`, `root_id`, `channel_name`,
|
||||
`message`, `sender_id`, `sender_name`, `version`, `is_crt_enabled`,
|
||||
`is_id_loaded`, and `signature`. The server signs push notifications with the
|
||||
`ack_id` and raw device token after splitting the stored device id into platform
|
||||
and token parts. The Android SDK stores device tokens with the
|
||||
`android_rn-v2:` compatibility prefix and validates the raw token portion.
|
||||
|
||||
ACK delivery uses `POST /api/v4/notifications/ack` with `id`, `received_at`,
|
||||
`platform`, `type`, `post_id`, and `is_id_loaded`. When id-loaded ACK is enabled
|
||||
for a message notification, the server may return post and routing fields that
|
||||
the SDK merges into the notification bundle.
|
||||
|
||||
The webapp remains the reference browser front. Compose and server updates must
|
||||
keep webapp messaging, replies, post acknowledgements, channel navigation, and
|
||||
thread behavior upstream-followable. Flutter embedded SDK compatibility is
|
||||
limited to payload fields, ACK/reply endpoints, signing-key verification,
|
||||
device-token format, and opened channel/thread routing events; product UI parity
|
||||
belongs to consuming apps or a separate roadmap item.
|
||||
|
||||
## Remote Parity
|
||||
|
||||
The remote development copy lives under `~/docker/services/nexo/compose`. Local
|
||||
|
|
|
|||
Loading…
Reference in a new issue