update project rules, roadmap, and README files across all domains

This commit is contained in:
toki 2026-05-27 21:41:23 +09:00
parent c9183529d8
commit 2b7330bbe9
10 changed files with 178 additions and 93 deletions

View file

@ -1,11 +1,14 @@
# nexo
`nexo` is a messaging and notification service workspace that keeps the server
core, Flutter client, and Flutter push-notification package together.
`nexo` is a Flutter messaging and notification package workspace. The main
deliverable is `packages/messaging_flutter`: a reusable package that lets many
Flutter apps integrate messaging and push-notification behavior without each app
reimplementing the same native runtime.
The current goal is to provide a Nexo-owned messaging service surface while
keeping the current server, client, and push runtime verifiable during the
transition.
Mattermost upstream repositories are kept as references around the package:
`apps/mattermost` for the original Mattermost app, `services/core` for the
server, and `services/push-proxy` for the push server. This repository does not
contain a dedicated nexo product app.
## Name
@ -14,9 +17,11 @@ notifications, and service infrastructure meet.
## Current Status
- `services/core/` is the messaging server core and compose runtime.
- `packages/messaging_flutter/` is an Android-first Flutter push-notification plugin.
- `apps/client/` is the Flutter client and integration test host for the plugin.
- `packages/messaging_flutter/` is the main product surface: an Android-first Flutter messaging and push-notification plugin package.
- `apps/flutter-test/` is the intended plugin test app. The current transitional path is `apps/client/`.
- `apps/mattermost/` is reserved for the original Mattermost app repository clone.
- `services/core/` is the Mattermost server repository clone.
- `services/push-proxy/` is reserved for the Mattermost push-proxy repository clone.
- Public package, import, and native identifiers are being moved to Nexo-owned names.
- iOS and macOS plugin scaffolds exist, but Android is the current implementation target.
@ -28,7 +33,7 @@ Show development entrypoints:
bin/dev
```
Run Flutter package and client checks:
Run Flutter package and `flutter-test` host checks:
```sh
bin/test
@ -47,16 +52,16 @@ docker compose up
| Purpose | Command | Notes |
| --- | --- | --- |
| Show development entrypoints | `bin/dev` | Prints client, plugin, and core compose commands |
| Show development entrypoints | `bin/dev` | Prints test host, plugin, and core compose commands |
| Run default tests | `bin/test` | Runs Flutter tests; skips Go tests by default |
| Run default lint | `bin/lint` | Runs Flutter analyze; skips Go vet by default |
| Run default build | `bin/build` | Runs client web build; skips Go build by default |
| Run default build | `bin/build` | Runs the transitional `apps/client` test-host web build; skips Go build by default |
| Include server Go tests | `NEXO_CORE_GO_TEST=1 bin/test` | Requires local `go` |
| Include server Go vet | `NEXO_CORE_GO_LINT=1 bin/lint` | Requires local `go` |
| Include server Go build | `NEXO_CORE_GO_BUILD=1 bin/build` | Requires local `go` |
| Run the client directly | `cd apps/client && flutter run` | Requires a device or emulator |
| Run the `flutter-test` host directly | `cd apps/client && flutter run` | Transitional path until `apps/flutter-test` exists |
| Test the plugin directly | `cd packages/messaging_flutter && flutter test` | Requires Flutter SDK |
| Run Android native unit tests | `cd apps/client/android && ./gradlew testDebugUnitTest` | Requires Android SDK |
| Run Android native unit tests | `cd apps/client/android && ./gradlew testDebugUnitTest` | Transitional path until `apps/flutter-test` exists |
The `bin/*` helpers skip checks when a required local tool is unavailable. Note
any skipped checks in work reports.
@ -65,10 +70,12 @@ any skipped checks in work reports.
| Path | Role |
| --- | --- |
| `services/core/` | Messaging server core, webapp, and API docs |
| `services/core/compose/` | Compose setup for core, Postgres, and push-proxy |
| `packages/messaging_flutter/` | Flutter push notification and messaging plugin |
| `apps/client/` | Flutter client and integration test host |
| `packages/messaging_flutter/` | Main Flutter messaging and push-notification package |
| `apps/flutter-test/` | Intended `flutter-test` app for package integration checks |
| `apps/client/` | Current transitional path for the `flutter-test` app |
| `apps/mattermost/` | Intended original Mattermost app repository clone |
| `services/core/` | Mattermost server repository clone and current compose runtime |
| `services/push-proxy/` | Intended Mattermost push-proxy repository clone |
| `docs/` | Cross-module product, migration, and operations notes |
| `bin/` | Workspace helper entrypoints |
| `agent-ops/` | Agent rules, domain rules, and common skill entrypoints |
@ -78,9 +85,16 @@ any skipped checks in work reports.
- Start by reading `AGENTS.md`, then `agent-ops/rules/project/rules.md`.
- Follow path-specific domain rules under `agent-ops/rules/project/domain/*/rules.md`.
- For standard tasks such as README, plan, review, or commit/push, route through `agent-ops/skills/common/router.md`.
- Treat `packages/messaging_flutter/` as the primary product. App-specific product UI and business logic belong in consuming apps outside this repository.
- Treat `apps/client/` only as the transitional `apps/flutter-test` path; do not grow it into a product app or duplicate plugin internals there.
- Treat `apps/mattermost`, `services/core`, and `services/push-proxy` as original Mattermost repository clones, not as nexo-owned app or server products.
- Do not change `services/core/UPSTREAM.md` baseline information without an explicit upstream decision.
- Keep product-specific `services/core/` changes small and easy to compare against upstream.
- Keep `apps/client/` as a thin consumer test host; do not duplicate plugin internals there.
- Keep upstream working clones outside this repository under a sibling/external `mattermost/` staging folder, one clone for each original repository.
- Track only upstream `main` in those staging clones. When `main` changes or a refresh is intentionally scheduled, take a fresh snapshot from staging and open a merge request into this repository.
- Record the exact upstream commit SHA for every snapshot that enters this repository.
- Prefer one merge request per upstream repository snapshot: `apps/mattermost`, `services/core`, or `services/push-proxy`.
- Never auto-apply staging updates into this repository; review the snapshot diff and run the relevant smoke checks first.
- Keep nexo-specific patches outside the upstream snapshot where possible, using compose, docs, wrappers, or small explicit patches.
## Development Flow

View file

@ -1,32 +1,35 @@
---
domain: client-app
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
last_rule_review_commit: c9183529d81f9b7ef458460c7195887e64f1eddb
last_rule_updated_at: 2026-05-27
---
# client-app
## 목적 / 책임
Flutter 클라이언트와 nexo 메시징 플러그인의 독립 소비 앱, 통합 테스트 호스트를 담당한다. 실제 제품 앱으로 확장되기 전에도 plugin integration이 깨지지 않는지 확인하는 기준점이다.
`apps/client`는 전환 전 `apps/flutter-test` 경로이며, nexo 메시징 플러그인을 검증하는 테스트용 Flutter 앱을 담당한다. 이 저장소의 제품 앱이 아니며, plugin integration이 깨지지 않는지 확인하는 기준점이다.
## 포함 경로
- `apps/client/lib/` — Flutter app source
- `apps/client/lib/` — 전환 전 Flutter test app source
- `apps/flutter-test/` — 목표 경로
- `apps/client/test/` — widget/unit tests
- `apps/client/integration_test/` — plugin integration tests
- `apps/client/android/`, `apps/client/ios/`, `apps/client/macos/` — host app platform configuration
- `apps/client/pubspec.yaml`app dependency and Flutter metadata
- `apps/client/pubspec.yaml`test host dependency and Flutter metadata
## 제외 경로
- `packages/messaging_flutter/` — push plugin 내부 구현 책임
- `apps/mattermost/` — 원래 Mattermost 앱 repository clone 책임
- `services/core/` — messaging server runtime 책임
- `services/push-proxy/` — Mattermost push-proxy repository clone 책임
- `docs/`, `bin/` — workspace 공통 문서와 command 책임
## 주요 구성 요소
- `MyApp` — plugin event stream과 navigation callback을 표시하는 host app shell
- `MyApp` — plugin event stream과 navigation callback을 표시하는 test host shell
- plugin singleton — app이 소비하는 plugin public API
- `plugin_integration_test.dart` — plugin integration behavior 검증 진입점
@ -36,15 +39,16 @@ Flutter 클라이언트와 nexo 메시징 플러그인의 독립 소비 앱, 통
- 앱에서는 token, notification, opened event, navigation callback 등 host integration만 검증한다.
- plugin 내부 native push 처리나 storage 로직을 앱으로 복제하지 않는다.
- Flutter check는 `bin/test`, `bin/lint`, 필요 시 `flutter test integration_test` 흐름을 따른다.
- 제품 앱 UI, app-specific business logic, 배포 앱 성격의 기능은 이 도메인에 추가하지 않는다.
## 다른 도메인과의 경계
- **messaging-flutter**: app은 plugin API 소비자이고, push 처리의 source of truth는 plugin이다.
- **messaging-flutter**: test app은 plugin API 소비자이고, push 처리의 source of truth는 plugin이다.
- **core-service**: server runtime이 필요한 테스트는 명시적으로 compose 또는 별도 환경을 켠 뒤 수행한다.
- **workspace-ops**: workspace command가 client 검증을 호출하지만 app 구조와 host behavior는 이 도메인이 소유한다.
- **workspace-ops**: workspace command가 test host 검증을 호출하지만 host 구조와 integration behavior는 이 도메인이 소유한다.
## 금지 사항
- 플러그인 버그를 우회하기 위해 app에 duplicate push 처리 경로를 만들지 않는다.
- generated Flutter platform 파일을 불필요하게 재생성하거나 대량 변경하지 않는다.
- 앱 검증 목적을 넘는 제품 기능을 사용자 요청 없이 크게 확장하지 않는다.
- 이 저장소 안의 nexo 제품 앱으로 확장하지 않는다.

View file

@ -1,19 +1,19 @@
---
domain: core-service
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
last_rule_review_commit: c9183529d81f9b7ef458460c7195887e64f1eddb
last_rule_updated_at: 2026-05-27
---
# core-service
## 목적 / 책임
nexo 메시징 서버 코어와 관련 웹앱, API 문서, 로컬 compose 실행 환경을 담당한다. upstream baseline과 비교 가능한 상태를 유지하는 것이 중요하다.
Mattermost 서버 repository clone을 담당한다. `packages/messaging_flutter` 검증에 쓰이더라도 nexo 독자 서버 제품으로 재정의하지 않고, 원본 repository 단위 갱신이 가능한 상태를 유지하는 것이 중요하다.
## 포함 경로
- `services/core/server/` — Go 기반 messaging server module
- `services/core/webapp/` — webapp, platform packages, frontend tooling
- `services/core/` — Mattermost 서버 repository clone
- `services/core/server/` — Mattermost server module
- `services/core/api/` — API reference tooling
- `services/core/compose/` — local core runtime Docker Compose
- `services/core/e2e-tests/`, `services/core/tools/` — core 검증 및 보조 도구
@ -22,31 +22,43 @@ nexo 메시징 서버 코어와 관련 웹앱, API 문서, 로컬 compose 실행
## 제외 경로
- `packages/messaging_flutter/` — Flutter push plugin 책임
- `apps/client/` — plugin consumer app 및 integration host 책임
- `apps/client/`, `apps/flutter-test/` — plugin 검증용 테스트 앱 책임
- `apps/mattermost/` — 원래 Mattermost 앱 repository clone 책임
- `services/push-proxy/` — Mattermost push-proxy repository clone 책임
- `docs/`, `bin/` — 워크스페이스 공통 운영 문서와 entrypoint 책임
## 주요 구성 요소
- `services/core/server/go.mod` — server Go module 기준
- `services/core/webapp/package.json` — webapp npm workspace 기준
- `services/core/api/package.json` — API reference tooling 기준
- `services/core/compose/docker-compose.yml` — local core 서비스 구성
## 유지할 패턴
- upstream에서 온 구조와 명명은 필요한 경우에만 변경한다.
- 제품 특화 변경은 좁은 파일 범위로 유지하고, upstream 재동기화를 방해하지 않게 설명 가능한 단위로 남긴다.
- 제품 특화 변경은 `packages/messaging_flutter` 검증에 필요한 범위로 좁게 유지하고, upstream 재동기화를 방해하지 않게 설명 가능한 단위로 남긴다.
- upstream 작업 clone은 이 저장소 밖의 sibling/external `mattermost/` staging 폴더에 둔다.
- staging clone은 upstream `main`만 따라가며, `main` 변경 시점 또는 의도적으로 정한 refresh 시점에 snapshot을 떠서 이 저장소의 `services/core`로 merge 요청한다.
- `services/core` snapshot 반영 시 upstream commit SHA를 `services/core/UPSTREAM.md`에 기록한다.
- `services/core` snapshot merge 요청은 앱 또는 push-proxy snapshot과 섞지 않는다.
- staging pull 결과를 자동 반영하지 않고, snapshot diff 확인과 core smoke 검증 후 merge 요청한다.
- 갱신은 잦은 자동 반영이 아니라 별도 작업선에서 검토하고, 통과한 baseline만 `services/core/UPSTREAM.md`와 runtime에 반영한다.
- nexo-specific patch는 가능한 한 upstream snapshot 밖의 compose, 문서, wrapper, 작은 명시 patch로 둔다.
- 개발 배포 방식은 현재 컨테이너 내부 개발 환경 제약을 고려해 별도 결정 전까지 고정하지 않는다.
- Go 검증은 기본 `bin/test`에서 skip되며, 필요할 때 `NEXO_CORE_GO_TEST=1` 등 명시적 플래그로 실행한다.
- webapp 변경은 기존 npm workspace와 package script를 따른다.
- 서버 clone 내부의 원본 repo 구조는 upstream 갱신을 우선해 불필요하게 재해석하지 않는다.
## 다른 도메인과의 경계
- **messaging-flutter**: server는 push payload와 ACK endpoint 성격을 제공하고, native 알림 표시와 device token 저장은 plugin이 담당한다.
- **client-app**: server runtime과 client host 검증은 분리한다. client app에서 server 내부 코드를 직접 수정하지 않는다.
- **client-app**: server runtime과 `flutter-test` 검증 앱은 분리한다. test app에서 server 내부 코드를 직접 수정하지 않는다.
- **push-proxy-service**: push-proxy는 `services/core` 하위 요소가 아니라 별도 원본 repository clone으로 둔다.
- **workspace-ops**: 공통 실행 스크립트가 core 명령을 호출할 수 있지만 core 내부 정책은 이 도메인이 소유한다.
## 금지 사항
- `services/core/UPSTREAM.md` baseline을 근거 없이 변경하지 않는다.
- 이 도메인을 nexo 제품 앱 또는 앱별 business logic의 소유 영역으로 확장하지 않는다.
- container-in-container 같은 개발 배포 방식을 현재 환경 기준으로 성급하게 고정하지 않는다.
- 대량 rename, formatting-only churn, upstream 파일의 광범위 재배치를 작업 범위 없이 수행하지 않는다.
- generated/build/cache 산출물을 소스 변경처럼 다루지 않는다.

View file

@ -1,14 +1,14 @@
---
domain: messaging-flutter
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
last_rule_review_commit: c9183529d81f9b7ef458460c7195887e64f1eddb
last_rule_updated_at: 2026-05-27
---
# messaging-flutter
## 목적 / 책임
nexo 메시징/알림 Flutter 플러그인을 담당한다. FCM 수신, 알림 표시, tap/open 이벤트, inline reply, dismiss 처리, ACK 전달, token/key 저장을 앱별 구현으로 흩어지지 않게 모다.
nexo의 메인 산출물인 메시징/알림 Flutter 플러그인 패키지를 담당한다. FCM 수신, 알림 표시, tap/open 이벤트, inline reply, dismiss 처리, ACK 전달, token/key 저장을 앱별 구현으로 흩어지지 않게 모아 여러 Flutter 앱이 재사용할 수 있게 한다.
## 포함 경로
@ -21,8 +21,10 @@ nexo 메시징/알림 Flutter 플러그인을 담당한다. FCM 수신, 알림
## 제외 경로
- `apps/client/` — plugin을 소비하는 host app 책임
- `services/core/` — server, webapp, API, compose runtime 책임
- `apps/client/`, `apps/flutter-test/` — plugin을 검증하는 테스트용 Flutter 앱 책임
- `apps/mattermost/` — 원래 Mattermost 앱 repository clone 책임
- `services/core/` — Mattermost 서버 repository clone 책임
- `services/push-proxy/` — Mattermost push-proxy repository clone 책임
- root `bin/` — workspace-level command entrypoint 책임
## 주요 구성 요소
@ -38,16 +40,18 @@ nexo 메시징/알림 Flutter 플러그인을 담당한다. FCM 수신, 알림
- public package/import/native identifier는 nexo 계열 이름으로 전환하되, host app과 native 등록 지점을 같은 계획 안에서 함께 갱신한다.
- Android가 production target이며 iOS/macOS는 stub 상태임을 명확히 보고한다.
- host app이 해야 할 Firebase 초기화, token 등록, navigation 연결은 README의 Host App Responsibilities와 맞춘다.
- 패키지를 이 저장소의 제품 중심으로 보고, 앱별 제품 UI나 business logic은 소비 앱 책임으로 둔다.
- native event type은 Dart API의 `PushNotificationType`과 호환되게 유지한다.
## 다른 도메인과의 경계
- **client-app**: client app은 integration host이며 plugin 내부 push 처리 로직을 복제하지 않는다.
- **core-service**: server와의 계약은 payload, signing key, auth token, ACK/reply endpoint 수준으로 다룬다.
- **client-app**: `apps/client`는 전환 전 `apps/flutter-test` 경로이며 plugin 내부 push 처리 로직을 복제하지 않는다.
- **core-service**: Mattermost 기반 runtime과의 계약은 payload, signing key, auth token, ACK/reply endpoint 수준으로 다룬다.
- **workspace-ops**: 공통 `bin/test`, `bin/lint`가 plugin 검증을 호출하지만 plugin 세부 검증 기준은 이 도메인이 소유한다.
## 금지 사항
- package rename이나 public API breaking change는 현재 마일스톤의 nexo 전환 결정과 계획에 맞춰 수행한다.
- host app 전용 navigation, 화면 구성, 제품 UI 상태를 plugin 내부에 넣지 않는다.
- 이 저장소 안에 nexo 제품 앱을 만들기 위해 plugin 책임을 앱 책임으로 옮기지 않는다.
- iOS/macOS stub을 production-ready로 단정하지 않는다.

View file

@ -1,7 +1,7 @@
---
domain: workspace-ops
last_rule_review_commit: 60eb73c2813f47e7157464bcd24b4db314c2ffce
last_rule_updated_at: 2026-05-26
last_rule_review_commit: c9183529d81f9b7ef458460c7195887e64f1eddb
last_rule_updated_at: 2026-05-27
---
# workspace-ops
@ -20,9 +20,11 @@ last_rule_updated_at: 2026-05-26
## 제외 경로
- `services/core/`core server, webapp, API 구현 책임
- `services/core/`Mattermost 서버 repository clone 책임
- `packages/messaging_flutter/` — Flutter push plugin 구현 책임
- `apps/client/` — client host app 구현 책임
- `apps/client/`, `apps/flutter-test/` — plugin 검증용 테스트 앱 책임
- `apps/mattermost/` — 원래 Mattermost 앱 repository clone 책임
- `services/push-proxy/` — Mattermost push-proxy repository clone 책임
- `agent-ops/rules/common/**`, `agent-ops/skills/common/**` — 공통 framework 파일이며 프로젝트에서 직접 수정하지 않는다.
## 주요 구성 요소
@ -43,7 +45,7 @@ last_rule_updated_at: 2026-05-26
- **core-service**: workspace script가 core 검증을 호출할 수 있지만 core 내부 명령 선택은 core 규칙을 따른다.
- **messaging-flutter**: plugin 검증은 workspace script로 실행할 수 있으나 API/플랫폼 계약은 plugin 도메인이 소유한다.
- **client-app**: client 검증은 workspace script로 실행할 수 있으나 app behavior는 client 도메인이 소유한다.
- **client-app**: `flutter-test` 검증 앱은 workspace script로 실행할 수 있으나 host behavior는 client 도메인이 소유한다.
## 금지 사항

View file

@ -7,13 +7,16 @@
## 프로젝트 개요
`nexo`는 메시징 서버, Flutter 클라이언트, Flutter 푸시 알림 패키지를 한 워크스페이스에서 함께 관리하는 프로젝트다.
`nexo`는 여러 Flutter 앱이 메시징/푸시 기능을 사용할 수 있게 하는 `packages/messaging_flutter` 패키지를 중심으로 관리하는 프로젝트다.
Mattermost 원본은 앱, 서버, push 서버 repository clone 단위로 둔다. 이 저장소에 별도 nexo 제품 앱을 싣지 않는다.
주요 경계는 다음과 같다.
- `services/core/` — nexo 메시징 서버 코어, 웹앱, API 문서, compose 환경
- `packages/messaging_flutter/` — nexo 메시징/알림 Flutter 플러그인
- `apps/client/` — 플러그인을 검증하는 Flutter 클라이언트와 통합 테스트 호스트
- `packages/messaging_flutter/` — nexo의 메인 산출물인 메시징/알림 Flutter 플러그인 패키지
- `apps/flutter-test/` — 플러그인을 검증하는 테스트용 Flutter 앱. 현재 전환 전 경로는 `apps/client/`
- `apps/mattermost/` — 원래 Mattermost 앱 repository clone
- `services/core/` — Mattermost 서버 repository clone
- `services/push-proxy/` — Mattermost push-proxy repository clone
- `docs/`, `bin/` — 워크스페이스 공통 문서와 helper entrypoint
## 기술 스택
@ -22,16 +25,24 @@
- Android native plugin: Kotlin, Java, Gradle
- iOS / macOS plugin scaffold: Swift
- Server core: Go `1.24.13`, messaging server module
- Webapp / API tooling: Node.js, npm workspaces, TypeScript, Redocly
- Mattermost app/API tooling: Node.js, npm workspaces, TypeScript, Redocly
- Local runtime: Docker Compose under `services/core/compose/`
## 작업 원칙
- `services/core/`는 upstream 계승 구조가 크므로 제품 특화 변경은 작고 비교 가능하게 유지한다.
- `packages/messaging_flutter/`를 제품 중심으로 본다. 앱별 제품 UI와 business logic은 이 저장소가 아니라 패키지를 소비하는 앱의 책임이다.
- `apps/client/`는 전환 전 `apps/flutter-test` 경로로만 본다. 플러그인 integration 검증을 넘는 제품 기능을 키우지 않는다.
- `apps/mattermost`, `services/core`, `services/push-proxy`는 Mattermost 원본 repository clone으로 유지한다. nexo 제품 앱이나 독자 서버 제품으로 재정의하지 않는다.
- upstream 작업 clone은 이 저장소 밖의 sibling/external `mattermost/` staging 폴더에 원본 repository별로 둔다.
- staging clone은 upstream `main`만 따라간다. `main` 변경 시점 또는 의도적으로 정한 refresh 시점에 snapshot을 떠서 이 저장소로 merge 요청한다.
- 이 저장소에 들어오는 snapshot은 원본 repository별 commit SHA를 기록한다.
- merge 요청은 원칙적으로 upstream repository별로 분리한다. 앱, 서버, push-proxy snapshot을 한 요청에 섞지 않는다.
- staging pull 결과를 이 저장소에 자동 반영하지 않는다. snapshot diff 확인과 관련 smoke 검증 후 merge 요청한다.
- nexo-specific patch는 가능한 한 upstream snapshot 밖의 compose, 문서, wrapper, 작은 명시 patch로 둔다.
- upstream 기능 단위 추적이나 잦은 자동 반영은 하지 않는다.
- `services/core/UPSTREAM.md`의 baseline 정보를 임의로 바꾸지 않는다.
- Flutter 플러그인의 public package/import/native identifier는 nexo 계열 이름으로 전환한다. 전환은 소비 앱과 native 등록 지점을 함께 다루는 계획 작업으로 진행한다.
- 푸시 알림 처리 책임은 `packages/messaging_flutter/`에 두고, `apps/client/`에는 검증과 host integration만 둔다.
- `apps/client/`는 독립 소비 앱 역할을 하므로 플러그인 내부 동작을 복제하지 않는다.
- 푸시 알림 처리 책임은 `packages/messaging_flutter/`에 두고, `apps/flutter-test`에는 검증과 host integration만 둔다.
- `build/`, `.dart_tool/`, Android/iOS/macOS 생성물, upstream bulk 파일은 요청 범위 밖이면 건드리지 않는다.
- 모듈별 README가 있는 경우 해당 모듈 안의 설명을 우선한다.
@ -53,6 +64,9 @@
| `services/core/**` | core-service | `agent-ops/rules/project/domain/core-service/rules.md` |
| `packages/messaging_flutter/**` | messaging-flutter | `agent-ops/rules/project/domain/messaging-flutter/rules.md` |
| `apps/client/**` | client-app | `agent-ops/rules/project/domain/client-app/rules.md` |
| `apps/flutter-test/**` | client-app | `agent-ops/rules/project/domain/client-app/rules.md` |
| `apps/mattermost/**` | mattermost-app | 생성 예정 |
| `services/push-proxy/**` | push-proxy-service | 생성 예정 |
| `docs/**`, `bin/**`, root docs/config | workspace-ops | `agent-ops/rules/project/domain/workspace-ops/rules.md` |
## 스킬 라우팅

View file

@ -7,8 +7,8 @@
## 목표
Mattermost server, webapp, push-proxy compose와 원격 Docker 세팅을 nexo의 반복 가능한 테스트 런타임으로 고정한다.
nexo용 포트, 환경 변수, 데이터 경로, push-proxy 설정을 분리하되 upstream update를 따라가기 쉬운 runtime shape를 유지한다.
Mattermost 앱, 서버, push-proxy 원본 repository clone과 원격 Docker 세팅을 `packages/messaging_flutter`의 반복 가능한 검증 기준선으로 고정한다.
nexo용 포트, 환경 변수, 데이터 경로, push-proxy 설정을 분리하되 원본 repository 단위의 주기적 upstream refresh를 따라가기 쉬운 runtime shape를 유지한다.
## 상태
@ -24,35 +24,53 @@ nexo용 포트, 환경 변수, 데이터 경로, push-proxy 설정을 분리하
- 결정 필요:
- 없음
- 결정 완료:
- [x] 2026-05-27: Mattermost server/webapp/push-proxy는 nexo가 deep fork하지 않고 upstream-followable runtime으로 유지한다.
- [x] 2026-05-27: Mattermost 앱, 서버, push-proxy는 nexo가 deep fork하지 않고 원본 repository clone 단위로 유지한다.
- [x] 2026-05-27: 로컬/개발/원격 개발 환경은 포트 직접 접근을 기준으로 하고, 운영 환경은 nginx 등 reverse proxy와 TLS/SSL 기반 노출을 원칙으로 하되 이 Milestone 범위에서는 다루지 않는다.
- [x] 2026-05-27: push-proxy credential은 현재 Milestone에서 테스트/운영 분리를 강제하지 않고, 실제 값이 git에 들어가지 않는 secret boundary와 compose 규격 유지 기준만 고정한다. 운영 credential 분리와 관리 방식은 실제 운영 배포 단계에서 결정한다.
- [x] 2026-05-27: 이 저장소의 메인 산출물은 `packages/messaging_flutter`이며, `apps/client`는 전환 전 `apps/flutter-test` 경로로 둔다. `apps/mattermost`는 원래 Mattermost 앱 repository clone이고 nexo 제품 앱이 아니다.
- [x] 2026-05-27: upstream 작업 clone은 이 저장소 밖의 sibling/external `mattermost/` staging 폴더에 원본 repository별로 두고, upstream `main`만 따라간다. `main` 변경 시점 또는 의도적으로 정한 refresh 시점에 snapshot을 떠서 이 저장소로 merge 요청한다.
- [x] 2026-05-27: snapshot 반영 시 원본 repository별 commit SHA를 기록하고, merge 요청은 앱/서버/push-proxy별로 분리한다. staging pull 결과를 자동 반영하지 않고 snapshot diff와 관련 smoke 검증 후 반영한다.
- [x] 2026-05-27: nexo-specific patch는 가능한 한 upstream snapshot 밖의 compose, 문서, wrapper, 작은 명시 patch로 둔다.
- [x] 2026-05-27: push-proxy도 latest image만 참조하는 외부 런타임으로 두지 않고, Mattermost push-proxy 원본 repository clone을 `services/push-proxy` 기준선으로 둔다. 다만 개발 배포 방식과 local build 전환은 현재 컨테이너 내부 개발 환경 제약상 이 Milestone에서 확정하지 않는다.
## 범위
- `services/core/compose/`의 compose와 `.env.example`
- `services/core/server/`, `services/core/webapp/`의 upstream-followable runtime 경계
- push-proxy image/source tracking과 credential/config 경계
- `services/core/`의 Mattermost 서버 repository clone 경계
- `services/push-proxy/`의 Mattermost push-proxy repository clone 경계
- `apps/mattermost/`의 원래 Mattermost 앱 repository clone 경계
- `apps/client`를 전환 전 `apps/flutter-test` 경로로 유지하는 검증 앱 경계
- 원격 개발 `~/docker/services/nexo/` 배치와 로컬 compose의 동등성
- core, webapp, Postgres, push-proxy 최소 health check
- core, Postgres, push-proxy, Mattermost 앱 접근 최소 health check
- runtime data와 secret이 git에 들어가지 않도록 유지하는 규칙
## 기능
### Epic: [compose] Core compose
local과 원격 Docker에서 같은 shape로 server/webapp/push-proxy 런타임을 올릴 수 있게 한다.
local과 원격 Docker에서 같은 shape로 Mattermost 서버와 push-proxy 런타임을 올릴 수 있게 한다.
- [ ] [local-compose] `services/core/compose`에서 core, webapp, db, push-proxy가 함께 실행되는 기준을 유지한다. 검증: `cd services/core/compose && docker compose up -d` 후 core ping과 webapp 접근이 성공한다.
- [ ] [local-compose] `services/core/compose`에서 core, db, push-proxy가 함께 실행되는 기준을 유지한다. 검증: `cd services/core/compose && docker compose up -d` 후 core ping과 Mattermost 앱 접근이 성공한다.
- [ ] [remote-parity] 원격 `~/docker/services/nexo/compose`와 repo의 compose 파일이 의도적으로 동기화되는 절차를 문서화한다. 검증: local/remote compose와 `.env.example` hash 비교가 일치한다.
- [ ] [secret-boundary] `.env`, data, push-proxy credential이 git 추적 밖에 머무는 기준을 유지한다.
- [ ] [upstream-runtime] server/webapp/push-proxy runtime은 official image/source baseline을 추적하고, nexo 변경은 compose/env/docs/thin patch로 제한하는 기준을 문서화한다.
### Epic: [upstream] Upstream baseline
Mattermost 앱, 서버, push-proxy를 nexo 제품 앱이 아니라 원본 repository clone으로 단순하게 추적한다.
- [ ] [upstream-repos] 외부 `mattermost/` staging 폴더에 Mattermost 앱, 서버, push-proxy 원본 repository clone을 두고 upstream `main`만 따라가는 기준을 기록한다.
- [ ] [snapshot-record] 이 저장소에 반영하는 각 snapshot의 upstream repository, branch, commit SHA, 반영 경로를 기록하는 기준을 정한다.
- [ ] [snapshot-mr] snapshot merge 요청은 원칙적으로 앱/서버/push-proxy repository별로 분리하고, 자동 반영 없이 diff 확인과 관련 smoke 검증 후 요청하는 절차를 문서화한다.
- [ ] [push-proxy-source] push-proxy를 latest image 참조만으로 두지 않고, 원본 repository clone 또는 source snapshot을 `services/push-proxy` 기준선에서 재현 가능한 형태로 포함한다.
- [ ] [refresh-workline] upstream `main` 변경 시점 또는 의도적으로 정한 refresh 시점에 외부 staging clone에서 snapshot을 떠서 이 저장소로 merge 요청하는 절차를 문서화한다.
- [ ] [nexo-patch-boundary] nexo-specific patch를 upstream snapshot과 섞지 않고 compose, 문서, wrapper, 작은 명시 patch로 유지하는 기준을 문서화한다.
- [ ] [runtime-boundary] `apps/mattermost`는 원래 Mattermost 앱 repository clone으로 선언하고, `apps/client`는 전환 전 `apps/flutter-test` 경로로만 유지한다.
### Epic: [smoke] Runtime smoke
서버 런타임 변경 후 최소 확인 절차를 작게 유지한다.
- [ ] [health-check] core `/api/v4/system/ping`, webapp 접근, db readiness를 로컬과 원격에서 확인하는 절차를 문서화한다.
- [ ] [health-check] core `/api/v4/system/ping`, Mattermost 앱 접근, db readiness를 로컬과 원격에서 확인하는 절차를 문서화한다.
- [ ] [push-proxy-check] push-proxy가 core에서 참조 가능한 위치에 뜨는지 확인하는 smoke 기준을 정한다.
## 완료 리뷰
@ -69,13 +87,20 @@ local과 원격 Docker에서 같은 shape로 server/webapp/push-proxy 런타임
- nginx/domain 연결, TLS/SSL, production hardening은 이 Milestone의 필수 범위가 아니다.
- 운영 credential 분리와 외부 secret manager 등 운영 secret 관리 방식 확정은 실제 운영 배포 기준이 생길 때 다룬다.
- 서버/front/push-proxy를 nexo 자체 deep fork 이미지로 바꾸는 작업은 별도 결정 후 진행한다.
- Mattermost 앱/서버/push-proxy를 nexo 자체 deep fork로 바꾸는 작업은 별도 결정 후 진행한다.
- 개발 배포 방식, local build 전환, container-in-container 기반 검증 방식은 현재 환경 제약상 이 Milestone에서 확정하지 않는다.
- upstream 기능 단위 추적, 세부 lifecycle 관리, 잦은 자동 반영, 여러 upstream repository snapshot을 한 merge 요청에 섞는 방식은 이 Milestone의 목표가 아니다.
- nexo 제품 앱 또는 앱별 제품 UI/business logic은 이 저장소 범위가 아니다.
- 기존 운영 중인 다른 compose 서비스와의 병합은 이 Milestone에서 자동으로 하지 않는다.
## 작업 컨텍스트
- 관련 경로: `services/core/compose/`, `services/core/UPSTREAM.md`, `services/core/server/`, `services/core/webapp/`
- 표준선(선택): compose는 core service 내부에 두고, server/webapp/push-proxy는 upstream-followable runtime으로 유지하며 별도 `infra/` 모듈은 만들지 않는다
- 관련 경로: `services/core/compose/`, `services/core/UPSTREAM.md`, `services/core/`, `services/push-proxy/`, `apps/mattermost/`, `apps/client/`
- 표준선(선택): compose는 core service 내부에 두고, Mattermost 앱/서버/push-proxy는 원본 repository 단위로 refresh 가능한 upstream clone으로 유지하며 별도 `infra/` 모듈은 만들지 않는다
- 제품 경계: 이 저장소의 메인 산출물은 `packages/messaging_flutter`이고, `apps/client`는 전환 전 `apps/flutter-test` 경로다. nexo 제품 앱은 이 저장소에 만들지 않는다.
- upstream 기준: Mattermost 앱/서버/push-proxy 작업 clone은 이 저장소 밖의 `mattermost/` staging 폴더에서 upstream `main`만 따라가고, 이 저장소에는 검토된 snapshot을 merge 요청으로 반영한다.
- snapshot 기준: 이 저장소에 들어온 snapshot은 upstream repository, branch, commit SHA, 반영 경로를 기록한다. merge 요청은 원칙적으로 upstream repository별로 분리한다.
- patch 기준: nexo-specific patch는 upstream snapshot 내부에 섞지 않고 compose, 문서, wrapper, 작은 명시 patch로 유지한다.
- 환경 노출 기준: 로컬/개발/원격 개발은 포트 직접 접근을 기준으로 하고, 운영은 reverse proxy와 TLS/SSL 기반 노출을 원칙으로 하되 후속 운영화 단계에서 다룬다.
- credential 기준: 실제 credential 값은 git 밖에 두고, `.env.example`에는 변수명과 기대 경로/형식만 남긴다. 테스트/운영 credential 강제 분리는 실제 운영 배포 단계에서 결정한다.
- 선행 작업: core compose 원격 테스트 배치

View file

@ -1,11 +1,13 @@
# nexo_client
# flutter-test
Flutter client and integration test host for the Nexo messaging runtime.
Transitional path: `apps/client`. Intended path: `apps/flutter-test`.
Test-only Flutter app for the Nexo messaging package.
## Purpose
This app is the workspace client harness. Keep it small and focused on proving
the messaging/notification package contract:
This app is the workspace test harness for `packages/messaging_flutter`. Keep it
small and focused on proving the messaging/notification package contract:
- plugin registration in a real Flutter application
- method-channel calls from Dart to the native plugin
@ -14,17 +16,19 @@ the messaging/notification package contract:
- Android manifest merge behavior
- manual Firebase FCM and nexo server ACK smoke testing
Product-specific UI should stay small until Nexo's messaging surface is ready.
This app should keep the minimum surface needed to prove package integration.
This app is not a nexo product app and is not the original Mattermost app. The
original Mattermost app belongs under `apps/mattermost/`; app-specific product
UI and business logic belong in consuming apps outside this repository.
## Structure
```text
apps/client/
lib/ # Small harness UI
# transitional path for apps/flutter-test/
lib/ # Small test harness UI
test/ # Widget tests for the harness
integration_test/ # Device/emulator plugin integration tests
android/ # Android app used to host the plugin
android/ # Android test host used to load the plugin
ios/ # iOS host scaffold
macos/ # macOS host scaffold
```
@ -78,5 +82,7 @@ repository-level remote environment guide:
- Keep the app thin.
- Prefer deterministic test controls over product-like UI.
- Do not add consuming-app business logic here.
- Do not grow this host into a nexo product app.
- Do not use this path for the original Mattermost app; that belongs under `apps/mattermost/`.
- Add integration tests here when a plugin behavior needs a real Flutter host.
- Keep manual FCM and server checks documented with the owning module.

View file

@ -6,10 +6,9 @@ root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cat <<EOF
nexo development entrypoints:
client app: cd "$root/apps/client" && flutter run
plugin package: cd "$root/packages/messaging_flutter" && flutter test
core compose: cd "$root/services/core/compose" && docker compose up
flutter-test host: cd "$root/apps/client" && flutter run
plugin package: cd "$root/packages/messaging_flutter" && flutter test
core compose: cd "$root/services/core/compose" && docker compose up
Start only the pieces you need.
EOF

View file

@ -25,12 +25,13 @@ packages/messaging_flutter/
ios/ # iOS plugin scaffold
macos/ # macOS plugin scaffold
test/ # Dart unit tests for the plugin contract
../../apps/client/ # Workspace client and integration test host
../../apps/client/ # Transitional path for apps/flutter-test
```
The workspace `apps/client/` app is the official independent consumer app for
this package. Use it to validate plugin integration without coupling tests to a
separate product app.
The workspace `apps/client/` app is the transitional path for the intended
`apps/flutter-test/` app. Use it to validate plugin integration without turning
this repository into a product-app workspace. The original Mattermost app belongs
under `apps/mattermost/`, not in the test host.
## How It Works
@ -184,7 +185,8 @@ Host apps should not redeclare duplicate FCM services unless they intentionally
coordinate that behavior with this plugin.
Android Gradle tests require a configured Android SDK through `ANDROID_HOME` or
`apps/client/android/local.properties`.
`apps/client/android/local.properties` while the test app is still on its
transitional path.
## Development Commands
@ -195,7 +197,7 @@ flutter analyze
flutter test
```
Run client-app checks:
Run `flutter-test` checks from the transitional path:
```sh
cd apps/client
@ -227,10 +229,13 @@ Use the repository tests as the source of truth for plugin behavior:
device-token formatting.
2. `android/src/test/` should cover native payload parsing, signing-key lookup,
local storage, notification behavior, and ACK request behavior.
3. `apps/client/test/` covers the thin Flutter harness app.
3. `apps/client/test/` covers the thin Flutter test app until it moves to
`apps/flutter-test/`.
4. `apps/client/integration_test/` covers real plugin registration,
method-channel behavior, event-channel behavior, notification-open routing,
and manifest integration on a device or emulator using the test/debug injection path.
and manifest integration on a device or emulator using the test/debug
injection path. This path is transitional until the test app moves to
`apps/flutter-test/`.
5. Manual smoke tests cover true Firebase FCM delivery and real nexo server ACK
flows because they depend on external infrastructure.
@ -258,5 +263,5 @@ Use this checklist before promoting a plugin change to a consuming app:
- Android is the only implemented runtime target.
- iOS and macOS are scaffolded but no-op.
- Full FCM delivery cannot be reliably automated in a headless test runner.
- The `apps/client/` app is intentionally small and should stay focused on
Nexo client and package integration behavior.
- The `apps/client/` app is the transitional `apps/flutter-test` path and should
stay focused on package integration behavior.