Flutter Web foreground 알림을 준비하기 위해 초기화 옵션과 token prefix 경계를 public API로 고정한다. 포트/환경 기준 문서와 로드맵 정리, agent-task 리뷰 산출물도 함께 반영한다.
216 lines
10 KiB
Markdown
216 lines
10 KiB
Markdown
# Core Compose
|
|
|
|
This compose file mirrors the current Mattermost-based runtime shape inside the
|
|
`services/core` module.
|
|
|
|
## Local Runtime
|
|
|
|
```sh
|
|
cd services/core/compose
|
|
cp -n .env.example .env
|
|
docker compose pull
|
|
docker compose up -d
|
|
```
|
|
|
|
`latest` is the verified stable pointer for nexo-owned runtime images.
|
|
When running or updating, you should run `docker compose pull && docker compose up -d` to fetch the latest stable images.
|
|
|
|
Runtime state is written to `services/core/data/`, which is ignored by git.
|
|
Place push-proxy configuration under
|
|
`services/core/data/push-proxy/config/mattermost-push-proxy.json` when FCM smoke
|
|
testing is needed.
|
|
|
|
The default host ports are `18065` for core and `18066` for push-proxy so this
|
|
test deployment can run beside the existing Mattermost service.
|
|
|
|
The Docker network subnet is fixed to `172.38.0.0/16`. Treat this range as
|
|
reserved for nexo and do not reuse it for other Docker networks.
|
|
|
|
## Port And Environment Inventory
|
|
|
|
This compose file is the source of truth for the nexo-owned runtime port shape.
|
|
It keeps public development defaults stable, while private hostnames,
|
|
credentials, tokens, and concrete remote endpoints stay in ignored environment
|
|
profiles or private run logs.
|
|
|
|
### Nexo Runtime
|
|
|
|
| Surface | Host publish | Container or internal target | Notes |
|
|
| --- | --- | --- | --- |
|
|
| Core HTTP and webapp | `${NEXO_CORE_PORT:-18065}` | `core:8065` | Compatibility baseline. Keep as-is unless a migration plan updates consumers. |
|
|
| Push-proxy HTTP | `${NEXO_PUSH_PROXY_PORT:-18066}` | `push-proxy:8066` | Host publish is for smoke and diagnostics. Core talks to `http://push-proxy:8066` on the compose network. |
|
|
| Postgres | none | `db:5432` | Compose-internal only. Do not publish by default. |
|
|
| Flutter test host | none | device/emulator app process | Runtime URL values belong in ignored local profiles or the invoking shell. |
|
|
| Flutter web preview | `13040` candidate | future web host | Reserved frontend slot for a future web preview; this repository currently does not publish a Flutter web host by default. |
|
|
|
|
### Upstream Dev Services
|
|
|
|
The Mattermost upstream development compose files under
|
|
`services/core/server/` publish several common local ports. Treat them as
|
|
upstream dev auxiliaries, not nexo runtime ports.
|
|
|
|
| Upstream service | Typical host publish | Role |
|
|
| --- | --- | --- |
|
|
| Mattermost dev proxy/server | `8065` | Upstream server/webapp development entrypoint |
|
|
| PostgreSQL | `5432` | Upstream dev database |
|
|
| Redis | `6379` | Upstream cache/session auxiliary |
|
|
| MinIO / console | `9000`, `9002` | Upstream object storage and console |
|
|
| Azurite | `10000` | Upstream Azure storage emulator |
|
|
| Inbucket web / SMTP / POP3 | `9001`, `10025`, `10110` | Upstream mail testing |
|
|
| OpenLDAP | `389`, `636` | Upstream LDAP testing |
|
|
| Elasticsearch / transport | `9200`, `9300` | Upstream search testing |
|
|
| OpenSearch | `9201` | Upstream search testing |
|
|
| DejaVu | `1358` | Upstream search dashboard |
|
|
| Keycloak | `8484 -> 8080` | Upstream SAML/OIDC testing |
|
|
| Prometheus | `9090` | Upstream metrics testing |
|
|
| Grafana | `3000` | Upstream dashboard testing |
|
|
| Loki | `3100` | Upstream log aggregation testing |
|
|
| OTel collector | `13133` | Upstream telemetry collector health |
|
|
|
|
If these upstream ports conflict with local services, change the upstream dev
|
|
compose invocation or environment for that run. Do not move nexo runtime
|
|
defaults just to satisfy an upstream dev auxiliary conflict.
|
|
|
|
### Slot Plan
|
|
|
|
- Frontend preview slot: reserve `13040` for a future Flutter/web preview.
|
|
- Backend compatibility slots: keep core `18065` and push-proxy `18066`.
|
|
- Compose-internal auxiliaries: keep DB/cache/object storage private to the
|
|
compose network unless a separate plan requires host access.
|
|
- Future backend migration candidate: if `18065`/`18066` must move, use a
|
|
planned `18040` range migration with compatibility notes and consumer smoke
|
|
evidence instead of changing defaults in place.
|
|
|
|
### Tracked Value Boundary
|
|
|
|
Tracked files may name environment variable names, example paths, sanitized
|
|
profile labels, and non-secret public development defaults. Do not commit raw
|
|
Firebase or APNs files, Mattermost tokens, passwords, private hostnames,
|
|
private ports, or concrete remote endpoint URLs. Store those values in ignored
|
|
`.env` files, ignored runtime data, or private test profiles, and refer to
|
|
sanitized evidence locations from public reports.
|
|
|
|
## Secret Boundary
|
|
|
|
Commit only `.env.example`. Keep `.env`, runtime data, logs, push-proxy
|
|
credentials, certificates, and license files out of git. If a new credential or
|
|
runtime path is added, first add the example variable or documented path here,
|
|
then confirm the concrete value or generated file is ignored.
|
|
|
|
## Smoke Checks
|
|
|
|
Run these checks after `docker compose up -d`.
|
|
|
|
```sh
|
|
curl -fsS "http://localhost:${NEXO_CORE_PORT:-18065}/api/v4/system/ping"
|
|
docker compose exec db pg_isready -U mmuser -d mattermost
|
|
curl -fsSI "http://localhost:${NEXO_CORE_PORT:-18065}"
|
|
```
|
|
|
|
The core ping response should report `status` as `OK`, Postgres should accept
|
|
connections for the `mattermost` database, and the Mattermost app should return
|
|
an HTTP response from the mapped core port.
|
|
|
|
For the minimum push-proxy smoke, confirm the service is running and the core
|
|
service still points at the compose-network DNS name:
|
|
|
|
```sh
|
|
docker compose ps push-proxy
|
|
docker compose config | rg --fixed-strings \
|
|
"MM_EMAILSETTINGS_PUSHNOTIFICATIONSERVER=http://push-proxy:8066"
|
|
```
|
|
|
|
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/agent-service/nexo/compose`. Local
|
|
and remote compose inputs should match unless a work report explicitly records
|
|
an intentional temporary drift.
|
|
|
|
```sh
|
|
cd services/core/compose
|
|
sha256sum docker-compose.yml .env.example
|
|
ssh <host> 'cd ~/docker/agent-service/nexo/compose && sha256sum docker-compose.yml .env.example'
|
|
```
|
|
|
|
The two `sha256sum` outputs should match for both files before remote runtime
|
|
smoke is treated as equivalent to local compose smoke.
|
|
|
|
## Deployment Loop
|
|
|
|
The compose deployment loop uses the same input contract for dev, test, and
|
|
production-like lanes. The lane changes the target and promotion gate, not the
|
|
tracked compose file.
|
|
|
|
### Deployment Lanes
|
|
|
|
| Lane | Purpose | Promotion gate |
|
|
| --- | --- | --- |
|
|
| `dev` | Disposable runtime for local feature checks and compose iteration. | Compose config renders, services start, and the smoke checks above pass. |
|
|
| `test` | Shared validation lane for upstream baseline or image updates before release notes. | Compose inputs match the candidate branch, images pull by immutable tag or digest, smoke passes, and failures are classified. |
|
|
| `production-like` | Internal release rehearsal before a stable pointer is treated as deployable. | Image refs, compose input hashes, secret profile label, smoke evidence, and rollback ref are recorded together. |
|
|
|
|
Use immutable tags or digests for `test` and `production-like` candidates.
|
|
`latest` remains the stable pointer only after the candidate evidence is already
|
|
recorded.
|
|
|
|
### Secret Injection
|
|
|
|
Start each lane from `.env.example`, then keep the concrete env profile outside
|
|
git. A tracked report may name the secret profile label and rotation decision,
|
|
but must not include raw values, credential files, hostnames, ports, tokens, or
|
|
private endpoint paths.
|
|
|
|
Push-proxy FCM/APNS credentials stay under ignored runtime data. If a new secret
|
|
path is needed, add only the example variable or sanitized path contract here,
|
|
then confirm the concrete file remains ignored.
|
|
|
|
### Rollback Contract
|
|
|
|
Before applying a candidate, record the previous image refs, compose input
|
|
hashes, secret profile label, and data snapshot reference in the private run log.
|
|
The public release note or follow-up issue records only the rollback ref,
|
|
classification, and sanitized evidence pointer.
|
|
|
|
A rollback restores the previous image refs and secret profile, starts the same
|
|
compose services, and reruns the smoke checks above. If rollback smoke fails,
|
|
classify the failure as `server`, `webapp`, `push-proxy`, `SDK contract`, or
|
|
`infra`, then open the follow-up before another promotion attempt.
|