archive mattermost-messaging-android-smoke milestone and update client push notification

This commit is contained in:
toki 2026-05-27 10:03:18 +09:00
parent 234a8910dd
commit 1766cd8ffc
7 changed files with 160 additions and 74 deletions

View file

@ -0,0 +1,79 @@
# Milestone: Mattermost Messaging Android Smoke
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/external-integration/PHASE.md`
## 목표
`mattermost_push_plugin`이 서버와 같은 `../nexo` repo의 `packages/messaging_flutter` package로 합쳐지고, 알림 전용에서 메시징 지원까지 포함하는 방향으로 전환된 현재 상태를 Android 기준으로 검증한다. 사용자 테스트까지 진행하지 않고, 원격 Android SDK 환경에서 build가 통과하고 Mattermost 메시지/FCM 알림이 실제 Android runtime에 도착하는지 확인하는 데서 완료 범위를 닫는다.
## 상태
[완료]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- `apps/client` host와 `../nexo/packages/messaging_flutter` package 경계가 현재 messaging 방향성과 충돌하지 않는지 확인
- 원격 Android SDK runner에서 `apps/client`의 Android debug build 검증
- Android device 또는 emulator에서 앱 boot, Firebase 초기화, Mattermost auth/token handoff, 알림 callback이 깨지지 않는지 smoke 확인
- Mattermost 메시지 또는 push trigger를 통해 Android 시스템 알림이 도착하는지 확인
- 검증 중 드러나는 build/configuration regression은 smoke를 통과시키는 최소 수정 범위에서 처리
## 기능
### Epic: [android-smoke] Remote Android notification verification
Mattermost messaging package 전환 이후 Android build와 알림 수신 경로가 실제 환경에서 깨지지 않았는지 확인한다.
- [x] [scope-check] `apps/client`, `apps/client/push-notification-todo.md`, `../nexo/packages/messaging_flutter` 경계를 확인해 현재 repo 업데이트가 메시징 지원 방향성과 맞는지 정리한다.
- [x] [remote-build] `docs/test-environments.md#android-sdk-remote-runner` 기준 원격 Android SDK 환경에서 `apps/client``flutter pub get``flutter build apk --debug`를 통과시킨다. 검증: `toki@toki-labs.com``/Users/toki/jenkins/workspace/nomadcode/apps/client`에서 `flutter pub get``flutter build apk --debug`가 통과했다.
- [x] [runtime-smoke] Android device 또는 emulator에서 앱을 실행해 앱 boot, Firebase 초기화, Mattermost auth/token handoff가 crash 없이 진행되는지 확인한다. 검증: `emulator-5554`에서 앱 boot, Firebase 초기화, notification permission authorized, Mattermost login, auth token/signing key 저장, FCM device token 등록을 secret redaction 상태로 확인했다.
- [x] [notification-arrival] Mattermost 메시지 또는 push trigger로 Android 시스템 알림이 도착하는지 확인한다. 검증: Mattermost post trigger `201`, `NexoFirebaseMessagingService.onMessageReceived`, ACK 전송, Android `NotificationRecord(pkg=com.tokilabs.mattermost)`, Flutter event 전송을 확인했다.
- [x] [evidence-note] build와 알림 smoke 결과, 사용자 테스트 미포함 한계, 후속 보완이 필요한 경우를 완료 리뷰 근거로 남긴다. 검증: 아래 `완료 리뷰``작업 컨텍스트`에 secret 없이 evidence를 기록했다.
## 완료 리뷰
- 상태: 승인됨
- 요청일: 2026-05-27
- 완료 근거:
- 원격 Android SDK runner에서 `flutter pub get``flutter build apk --debug`가 통과했다.
- Android 14 emulator `emulator-5554`에서 앱 boot, Firebase 초기화, Mattermost login, auth token/signing key 저장, FCM device token 등록이 통과했다.
- Mattermost post trigger 후 FCM 수신, ACK 전송, Android system notification record, Flutter notification event 전송을 확인했다.
- 리뷰 필요:
- [x] 사용자가 완료 결과를 확인했다
- [x] archive 이동을 승인했다
- 리뷰 코멘트: 사용자 테스트/UAT는 범위 제외이며, 원격 smoke 중 token, password, signing key, FCM/device token은 문서에 기록하지 않았다. 사용자가 Mattermost 내 tester 메시지 도착과 `nomadcode` 웹 채널 메시지 도착도 확인했다.
## 범위 제외
- 사용자 테스트, UAT, 제품 사용성 검증
- iOS/macOS native push full implementation 또는 runtime smoke
- Mattermost 메시징 제품 UX 구현
- Mattermost server-side plugin 대규모 기능 확장
- External Integration Milestone의 Plane/Jira/Agent Integrator/IOP adapter 구현
## 작업 컨텍스트
- 관련 경로: `apps/client/`, `apps/client/push-notification-todo.md`, `docs/test-environments.md`, `../nexo/packages/messaging_flutter`
- 연관 core 경계: `services/core/internal/adapters/mattermost/`, `services/core/internal/notification/`
- 선행 작업: Mattermost Push Plugin Extraction, Client Integration Standardization
- 후속 작업: External Integration의 Mattermost 메시지 발송 adapter 구현
- 표준선: Android SDK 의존 검증은 `docs/test-environments.md#android-sdk-remote-runner`를 따른다.
- 보안 주의: Mattermost token, Firebase credential, signing key, device token은 roadmap이나 문서에 기록하지 않는다.
- 2026-05-26 scope-check: `apps/client` host dependency/import 문서를 `../nexo/packages/messaging_flutter`의 현재 Dart package명 `nexo_messaging``NexoMessagingPlugin` API에 맞췄고, ignored `assets/mattermost_credentials.json`을 smoke 때 bundle할 수 있도록 assets 디렉터리를 선언했다. 원격 Android build와 실제 알림 도착 smoke는 환경 의존 작업으로 plan에서 수행한다.
- 2026-05-26 runtime-smoke 준비: `~/docker/services/mattermost` 기준 Mattermost public URL은 `https://mattermost.toki-labs.com`, server-side push target은 `http://mattermost-push-proxy:8066`, push notification은 enabled 상태임을 확인했다. `nomadcode` 공개 채널 ID는 확인됐고, 값은 secret이 아니지만 재사용은 ignored `.env.mattermost.local`을 우선한다.
- 2026-05-26 runtime-smoke secret 상태: post trigger용 Mattermost PAT는 활성화되어 API `/api/v4/users/me``nomadcode` 채널 post가 성공했다. 토큰 값은 roadmap에 기록하지 않고, 로컬 및 원격 runner의 ignored `.env.mattermost.local`에 저장했다.
- 2026-05-26 남은 차단점: post trigger env는 준비됐지만 앱 수신자 등록은 아직 남았다. 현재 앱은 `assets/mattermost_credentials.json`에서 `serverUrl/loginId/password`만 읽어 로그인 후 FCM device token을 등록하므로, 테스트 사용자 credential asset을 준비하거나 token 기반 smoke credential 지원을 구현해야 한다.
- 2026-05-26 다음 재개 기준: 원격 runner에서 `.env.mattermost.local`을 로드해 trigger env를 주입하고, 앱 수신자 credential을 준비한 뒤 Android emulator에서 boot/FCM registration/post trigger/system notification evidence를 secret 없이 다시 기록한다. FCM/device token은 로그에 붙이기 전에 redaction한다.
- 2026-05-27 사용자 결정 해소: 앱 수신자 인증은 ignored `apps/client/assets/mattermost_credentials.json` 방식으로 준비하고, notification smoke 발신자는 앱 수신자와 분리된 테스트용 PAT를 사용한다. `apps/client/macos/Flutter/GeneratedPluginRegistrant.swift``apps/client/push-notification-todo.md` 변경은 `nexo_messaging` rename 정정으로 이번 smoke 범위에 포함한다.
- 2026-05-27 secret 준비 상태: 로컬과 원격 runner에 credential asset과 `.env.mattermost.local``0600` 권한으로 준비했고, 값 노출 없이 Mattermost 발신자 API 접근과 수신자 login/token header를 확인했다.
- 2026-05-27 원격 환경 정리: `toki@toki-labs.com``~/.nomadcode-env.sh``FLUTTER_HOME=$HOME/SDK/flutter`, `ANDROID_HOME=$HOME/Library/Android/sdk`, `ANDROID_SDK_ROOT=$ANDROID_HOME`, 관련 `PATH`를 설정하고 bash/zsh login shell에서 로드되도록 했다.
- 2026-05-27 smoke evidence: 원격 nexo package copy가 오래된 `MattermostPushPlugin` metadata를 들고 있어 `NexoMessagingPlugin` method channel이 누락된 것을 확인했고, 최신 `../nexo/packages/messaging_flutter` package로 원격 테스트 copy를 동기화한 뒤 Android generated registrant가 `com.tokilabs.nexo.messaging.NexoMessagingPlugin`을 등록하도록 재생성했다. 이후 debug APK build와 runtime smoke, notification arrival smoke가 통과했다.
- 2026-05-27 사용자 확인: 사용자가 Mattermost 내 tester 메시지 도착을 확인했고, `nomadcode` 채널 웹 메시지 발송도 정상 도착으로 확인했다.

View file

@ -15,9 +15,9 @@
- [계획] Workflow Core
- Phase: `agent-ops/roadmap/phase/workflow-core/PHASE.md`
- 경로: `agent-ops/roadmap/phase/workflow-core/milestones/workflow-core.md`
- [계획] Mattermost Messaging Android Smoke
- [계획] External Integration
- Phase: `agent-ops/roadmap/phase/external-integration/PHASE.md`
- 경로: `agent-ops/roadmap/phase/external-integration/milestones/mattermost-messaging-android-smoke.md`
- 경로: `agent-ops/roadmap/phase/external-integration/milestones/external-integration.md`
## 선택 규칙

View file

@ -13,9 +13,9 @@ Work Item Provider Pipeline Design과 Workflow Core 이후 Plane/Jira 확장, Ma
완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다.
완료, 검토중, 진행중, 계획 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다.
- [계획] Mattermost Messaging Android Smoke
- 경로: `agent-ops/roadmap/phase/external-integration/milestones/mattermost-messaging-android-smoke.md`
- 요약: `mattermost_push_plugin`이 `../nexo/packages/messaging_flutter`로 서버와 함께 합쳐지고 메시징 지원 방향으로 확장된 뒤, 원격 Android SDK 환경에서 build와 알림 도착 smoke를 확인한다.
- [완료] Mattermost Messaging Android Smoke
- 경로: `agent-ops/roadmap/archive/phase/external-integration/milestones/mattermost-messaging-android-smoke.md`
- 요약: `../nexo/packages/messaging_flutter` 전환 이후 원격 Android SDK build, emulator runtime, Mattermost FCM 알림 도착, 웹 채널 메시지 도착을 확인했다.
- [계획] External Integration
- 경로: `agent-ops/roadmap/phase/external-integration/milestones/external-integration.md`

View file

@ -1,67 +0,0 @@
# Milestone: Mattermost Messaging Android Smoke
## 위치
- Roadmap: `agent-ops/roadmap/ROADMAP.md`
- Phase: `agent-ops/roadmap/phase/external-integration/PHASE.md`
## 목표
`mattermost_push_plugin`이 서버와 같은 `../nexo` repo의 `packages/messaging_flutter` package로 합쳐지고, 알림 전용에서 메시징 지원까지 포함하는 방향으로 전환된 현재 상태를 Android 기준으로 검증한다. 사용자 테스트까지 진행하지 않고, 원격 Android SDK 환경에서 build가 통과하고 Mattermost 메시지/FCM 알림이 실제 Android runtime에 도착하는지 확인하는 데서 완료 범위를 닫는다.
## 상태
[계획]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- `apps/client` host와 `../nexo/packages/messaging_flutter` package 경계가 현재 messaging 방향성과 충돌하지 않는지 확인
- 원격 Android SDK runner에서 `apps/client`의 Android debug build 검증
- Android device 또는 emulator에서 앱 boot, Firebase 초기화, Mattermost auth/token handoff, 알림 callback이 깨지지 않는지 smoke 확인
- Mattermost 메시지 또는 push trigger를 통해 Android 시스템 알림이 도착하는지 확인
- 검증 중 드러나는 build/configuration regression은 smoke를 통과시키는 최소 수정 범위에서 처리
## 기능
### Epic: [android-smoke] Remote Android notification verification
Mattermost messaging package 전환 이후 Android build와 알림 수신 경로가 실제 환경에서 깨지지 않았는지 확인한다.
- [x] [scope-check] `apps/client`, `apps/client/push-notification-todo.md`, `../nexo/packages/messaging_flutter` 경계를 확인해 현재 repo 업데이트가 메시징 지원 방향성과 맞는지 정리한다.
- [ ] [remote-build] `docs/test-environments.md#android-sdk-remote-runner` 기준 원격 Android SDK 환경에서 `apps/client``flutter pub get``flutter build apk --debug`를 통과시킨다. 검증: 원격 host, branch/commit, 주요 command 결과를 secret 없이 evidence로 남긴다.
- [ ] [runtime-smoke] Android device 또는 emulator에서 앱을 실행해 앱 boot, Firebase 초기화, Mattermost auth/token handoff가 crash 없이 진행되는지 확인한다. 검증: `flutter run -d <device-id>` 또는 동등한 runtime 실행 결과를 남긴다.
- [ ] [notification-arrival] Mattermost 메시지 또는 push trigger로 Android 시스템 알림이 도착하는지 확인한다. 검증: 알림 도착 여부, 앱 callback 관찰 여부, 실패 시 원인 후보를 secret 없이 기록한다.
- [ ] [evidence-note] build와 알림 smoke 결과, 사용자 테스트 미포함 한계, 후속 보완이 필요한 경우를 완료 리뷰 근거로 남긴다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 없음
- 리뷰 필요:
- [ ] 사용자가 완료 결과를 확인했다
- [ ] archive 이동을 승인했다
- 리뷰 코멘트: 없음
## 범위 제외
- 사용자 테스트, UAT, 제품 사용성 검증
- iOS/macOS native push full implementation 또는 runtime smoke
- Mattermost 메시징 제품 UX 구현
- Mattermost server-side plugin 대규모 기능 확장
- External Integration Milestone의 Plane/Jira/Agent Integrator/IOP adapter 구현
## 작업 컨텍스트
- 관련 경로: `apps/client/`, `apps/client/push-notification-todo.md`, `docs/test-environments.md`, `../nexo/packages/messaging_flutter`
- 연관 core 경계: `services/core/internal/adapters/mattermost/`, `services/core/internal/notification/`
- 선행 작업: Mattermost Push Plugin Extraction, Client Integration Standardization
- 후속 작업: External Integration의 Mattermost 메시지 발송 adapter 구현
- 표준선: Android SDK 의존 검증은 `docs/test-environments.md#android-sdk-remote-runner`를 따른다.
- 보안 주의: Mattermost token, Firebase credential, signing key, device token은 roadmap이나 문서에 기록하지 않는다.
- 2026-05-26 scope-check: `apps/client` host dependency/import 문서를 `../nexo/packages/messaging_flutter`의 현재 Dart package명 `nexo_messaging``NexoMessagingPlugin` API에 맞췄고, ignored `assets/mattermost_credentials.json`을 smoke 때 bundle할 수 있도록 assets 디렉터리를 선언했다. 원격 Android build와 실제 알림 도착 smoke는 환경 의존 작업으로 plan에서 수행한다.

View file

@ -0,0 +1,74 @@
# User Review Resolved - m-mattermost-messaging-android-smoke/02+01_runtime_notification_smoke
## 요청 일시
2026-05-26
## 상태
RESOLVED
## 사유
- 유형: environment-blocked
- 현재 리뷰 회차: 1
- 최종 판정: RESOLVED
- 요약: Mattermost notification arrival smoke를 막던 외부 env와 credential 조건을 준비했고, 원격 Android runner에서 build, runtime smoke, FCM 수신, Android system notification, Mattermost 웹 채널 메시지 도착까지 확인했다.
## 루프 이력
| Plan | Review | Verdict | 메모 |
|------|--------|---------|------|
| `agent-task/archive/2026/05/m-mattermost-messaging-android-smoke/02+01_runtime_notification_smoke/plan_cloud_G08_0.log` | `agent-task/archive/2026/05/m-mattermost-messaging-android-smoke/02+01_runtime_notification_smoke/code_review_cloud_G08_0.log` | FAIL | Mattermost trigger env/credentials 부재로 Android notification arrival를 검증하지 못했고, FCM token redaction 및 검증 재현성 문제가 함께 발견됨 |
| manual follow-up | user-confirmed smoke | RESOLVED | secret/env 준비, 원격 Android runner 환경 설정, `NexoMessagingPlugin` 등록 보정, Android notification arrival, Mattermost 웹 채널 도착 확인으로 차단 해소 |
## 차단 근거
- 문제: `MATTERMOST_BASE_URL`, `MATTERMOST_TOKEN`, `MATTERMOST_TEST_CHANNEL_ID`, `assets/mattermost_credentials.json`이 없어 Mattermost post trigger와 Android system notification/callback 관찰을 수행할 수 없다.
- 현재 archive plan: `agent-task/archive/2026/05/m-mattermost-messaging-android-smoke/02+01_runtime_notification_smoke/plan_cloud_G08_0.log`
- 현재 archive review: `agent-task/archive/2026/05/m-mattermost-messaging-android-smoke/02+01_runtime_notification_smoke/code_review_cloud_G08_0.log`
- 검증 명령: `ssh -o BatchMode=yes -o ConnectTimeout=10 toki@toki-labs.com 'bash -lc '\''set -euo pipefail; cd ~/jenkins/workspace/nomadcode/apps/client; for n in MATTERMOST_BASE_URL MATTERMOST_TOKEN MATTERMOST_TEST_CHANNEL_ID; do if [ -n "${!n:-}" ]; then printf "%s=set\n" "$n"; else printf "%s=missing\n" "$n"; fi; done; if [ -f assets/mattermost_credentials.json ]; then printf "assets/mattermost_credentials.json=present\n"; else printf "assets/mattermost_credentials.json=missing\n"; fi'\'''`
- 실제 출력:
```text
MATTERMOST_BASE_URL=missing
MATTERMOST_TOKEN=missing
MATTERMOST_TEST_CHANNEL_ID=missing
assets/mattermost_credentials.json=missing
```
- 환경 판단 근거: 필수 Mattermost API token과 test channel, host credential asset은 repo에 커밋하면 안 되는 외부 secret/config이며, 현재 repository 내부 수정만으로는 실제 push trigger와 알림 도착 관찰을 만들 수 없다.
## 사용자 결정 처리
- [ ] 자동 follow-up plan/review를 계속 진행한다. (선택하지 않음)
- [ ] 계획을 재작성한다. (선택하지 않음)
- [x] 테스트 환경, secret, 외부 서비스, SDK, 장비 조건을 준비한 뒤 재시도한다.
- [ ] 작업 범위를 줄이거나 보류/폐기한다. (선택하지 않음)
## 재개 조건
- 충족됨: 원격 runner에서 Mattermost trigger env와 앱 auth handoff credential을 값 노출 없이 준비했다.
- 충족됨: FCM/device token redaction, 재현 가능한 Flutter command 경로, 현재 worktree의 mobile 변경 범위를 정리하고 smoke evidence를 남겼다.
## 다음 실행 힌트
- 닫힘: Milestone은 `[완료]`로 승인되어 roadmap archive로 이동했다. 후속 작업은 `External Integration` Milestone에서 adapter 구현 범위를 결정한 뒤 이어간다.
## 후속 업데이트
- 2026-05-26: Mattermost server/push-proxy 설정을 확인했다. public URL은 `https://mattermost.toki-labs.com`, server-side push target은 `http://mattermost-push-proxy:8066`, push notification은 enabled 상태다.
- 2026-05-26: `nomadcode` 채널 ID와 post trigger용 PAT 동작을 확인했고, 토큰 값은 기록하지 않고 로컬 및 원격 runner의 ignored `.env.mattermost.local`에 저장했다.
- 2026-05-26: post trigger env 차단은 해소됐지만 앱 수신자 credential 차단은 남아 있다. 현재 앱은 `apps/client/assets/mattermost_credentials.json``serverUrl/loginId/password`로 로그인한 뒤 FCM device token을 등록한다.
- 2026-05-27: 앱 수신자 인증은 ignored `apps/client/assets/mattermost_credentials.json` 방식으로 준비하기로 결정했다. 로컬과 원격 runner에 credential asset과 `.env.mattermost.local``0600` 권한으로 준비했고, 값 노출 없이 `MATTERMOST_*` env set 여부, 발신자 token의 user/channel API 접근, 수신자 login/token header를 확인했다.
- 2026-05-27: notification smoke 발신자는 앱 수신자와 분리된 테스트용 PAT를 사용한다. self-notification 회피를 위해 발신자와 수신자는 분리된 계정으로 유지한다.
- 2026-05-27: `apps/client/macos/Flutter/GeneratedPluginRegistrant.swift``apps/client/push-notification-todo.md` 변경은 `nexo_messaging` / `NexoFirebaseMessagingService` rename에 맞춘 정정으로 확인했으며, 이번 smoke 범위에 포함한다.
- 2026-05-27: 원격 Android runner의 `~/.nomadcode-env.sh`에 Flutter/Android SDK 환경 변수를 설정하고 bash/zsh login shell에서 로드되도록 했다. 이후 `flutter pub get`, `flutter build apk --debug`, Android emulator runtime smoke, Mattermost post trigger, FCM 수신, Android notification record 생성을 secret 없이 확인했다.
- 2026-05-27: 원격 `../nexo/packages/messaging_flutter` 테스트 copy가 stale `MattermostPushPlugin` metadata를 사용해 method channel이 빠진 문제를 확인했고, 최신 package copy로 동기화해 `NexoMessagingPlugin` 등록 후 smoke를 통과시켰다.
- 2026-05-27: 사용자가 Mattermost 내 tester 메시지 도착과 `nomadcode` 웹 채널 메시지 도착을 확인했다. `Mattermost Messaging Android Smoke` Milestone은 `[완료]`로 승인되어 roadmap archive로 이동했다.
## 사용자가 다음에 결정할 일
- [x] 앱 수신자 인증을 ignored `apps/client/assets/mattermost_credentials.json`으로 준비할지, 앱 credential loader에 token 기반 smoke credential 지원을 좁게 추가할지 결정한다.
- [x] notification smoke 발신자를 기존 `build` bot token으로 둘지, 사용자 PAT로 둘지 결정한다. self-notification 회피를 위해 발신자와 앱 수신자는 분리하는 것을 기본 후보로 둔다.
- [x] 현재 worktree의 `apps/client/macos/Flutter/GeneratedPluginRegistrant.swift`, `apps/client/push-notification-todo.md` 변경을 이번 smoke 범위에 포함할지 별도 정리할지 결정한다.

View file

@ -13,6 +13,6 @@ import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
MattermostPushPlugin.register(with: registry.registrar(forPlugin: "MattermostPushPlugin"))
NexoMessagingPlugin.register(with: registry.registrar(forPlugin: "NexoMessagingPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}

View file

@ -32,7 +32,7 @@ To keep host architectures generic and lightweight, we maintain a strict boundar
- Listen to token registration callbacks via the `onDeviceTokenReady` callback on `MattermostPushClient` interface, and forward the target device token back to the Mattermost backend server.
- *Note*: Production calls to `NexoMessagingPlugin.instance` are strictly isolated and encapsulated within the `MattermostPushPluginClient` adapter implementation, maintaining a generic, testable host bootstrap.
- **Nexo Messaging Plugin (`nexo_messaging`) Responsibilities**:
- Intercepting incoming FCM pushes via Kotlin services (`MattermostFirebaseMessagingService`).
- Intercepting incoming FCM pushes via Kotlin services (`NexoFirebaseMessagingService`).
- Parsing payloads and verifying cryptographic signatures with JJWT.
- Interacting with local SQLite database (Room DB).
- Building native system notifications, dismissing ACKs, and inline replies.