Files
fidelity-ai-workspace/scripts/mattermost-proxy/README.md

152 lines
5.8 KiB
Markdown

# Mattermost Proxy Mirror
Local read-only Mattermost Desktop mirror for AI workspace context.
This is for **raw evidence only**. It writes under `ai/inbox/mattermost-mirror/`; durable project memory still belongs in `project-knowledge/` after normal promotion rules.
## Why this exists
Mattermost Team Edition 11.4.2 exposes normal `/api/v4` REST and WebSocket traffic. When Mattermost Desktop is launched with Chromium/Electron's `--proxy-server` flag, `mitmproxy` can capture only that app without changing the macOS system proxy.
## Setup
1. Install `mitmproxy`.
2. Trust the mitmproxy certificate if HTTPS interception is not already working:
- Start `scripts/mattermost-proxy/run-mirror.sh`
- Open `http://mitm.it`
- Install/trust the certificate in Keychain.
3. Optional: copy `.env.example` to `.env` and set `MATTERMOST_MIRROR_HOST_ALLOW` to the exact Mattermost host, for example `mm.all-win-solutions.app`.
## Run day to day
Terminal 1:
```bash
scripts/mattermost-proxy/run-mirror.sh
```
Terminal 2:
```bash
scripts/mattermost-proxy/launch-mattermost.sh
```
This launches Mattermost Desktop through macOS LaunchServices with:
```bash
--proxy-server=http://127.0.0.1:8080
```
No global macOS proxy is required.
The helper intentionally uses `open -n /Applications/Mattermost.app --args ...`
instead of invoking `/Applications/Mattermost.app/Contents/MacOS/Mattermost`
directly. Direct binary launch can crash sandboxed Electron apps with Mach
rendezvous errors because their expected app/container parent process is
missing.
## Output layout
```text
ai/inbox/mattermost-mirror/
latest.jsonl # bounded AI-readable window
latest.md # bounded Markdown view
state.json # last seen by channel and user cache
index.json # date/channel/thread file map
refs/
channels.json # channel_id -> channel_name
users.json # user_id -> username
channels/<channel-name>/YYYY/MM/YYYY-MM-DD.jsonl
by-date/YYYY/MM/YYYY-MM-DD.jsonl
threads/<root-or-post-id>.jsonl
raw/YYYY/MM/YYYY-MM-DD-websocket.jsonl # only if MATTERMOST_MIRROR_WRITE_RAW=1
raw/YYYY/MM/YYYY-MM-DD-rest-flows.jsonl # only if MATTERMOST_MIRROR_WRITE_RAW=1
```
Use `latest.md` or `latest.jsonl` for quick AI context. Use `channels/...`
for conversation-focused analysis, `by-date/...` for standups or daily review,
and `threads/...` when a single discussion thread is the relevant evidence.
This mirrors Slack's export pattern of one folder per conversation with one file
per date, while adding Mattermost-specific thread views.
Direct-message channels are labeled as `dm-<user-a>--<user-b>` when the mirror
has seen enough user metadata to resolve the Mattermost channel ID. Group DMs
use `group-...`. If a DM was first captured before the relevant user metadata
arrived, the folder can temporarily use raw IDs; later captures use the readable
label and `refs/channels.json` remains the source for resolving channel IDs.
The mirror writes any post payload it sees, including older messages returned
when the desktop app loads channel history or a thread. It dedupes by `post_id`,
so scrolling back through useful history is a safe way to backfill missing local
evidence without creating repeated entries.
## Normalized message schema
Each line in the normalized JSONL contains:
```json
{
"source": "websocket|rest",
"captured_at": "2026-05-19T...Z",
"created_at": "2026-05-19T...Z",
"created_at_ms": 1779190000000,
"channel_id": "...",
"channel_name": "fidelity-preguntas",
"post_id": "...",
"root_id": "...",
"thread_id": "...",
"user_id": "...",
"username": "jeff",
"message": "...",
"type": "channel_post|thread_reply",
"raw_event": "posted|posts|post"
}
```
## Safety rules
- The addon allowlists Mattermost hosts and `/api/v4` traffic only.
- Headers such as `Authorization`, `Cookie`, `Set-Cookie`, and CSRF are redacted in optional raw output.
- Optional raw output is disabled by default to prevent large files.
- Attachments are not downloaded by this mirror.
- The mirror is evidence, not canonical memory.
## Useful environment variables
- `MATTERMOST_MIRROR_HOST_ALLOW`: exact host or parent domain to capture.
- `MATTERMOST_MIRROR_DIR`: output directory, default `ai/inbox/mattermost-mirror`.
- `MATTERMOST_MIRROR_LATEST_LIMIT`: number of messages in `latest.*`, default `200`.
- `MATTERMOST_MIRROR_CHANNEL_IDS`: optional comma-separated channel ID allowlist.
- `MATTERMOST_MIRROR_WRITE_RAW`: set to `1` to save compact raw REST/WebSocket evidence.
- `MATTERMOST_APP_PATH`: Mattermost Desktop `.app` bundle path.
## Troubleshooting
### TLS certificate warnings
Mitmproxy uses a persistent local CA under `~/.mitmproxy`. If the desktop app
asks about the certificate after every proxy restart, install and trust that CA
in macOS Keychain instead of approving it only in the app prompt:
1. Start `scripts/mattermost-proxy/run-mirror.sh`.
2. Open `http://mitm.it` from a browser on this Mac and download the macOS certificate.
3. Add it to Keychain Access and set it to **Always Trust**.
4. Restart Mattermost Desktop through `launch-mattermost.sh`.
Warnings for unrelated hosts such as `releases.mattermost.com` or OpenGraph
preview hosts are not required for message capture. The mirror only writes
normalized messages from Mattermost `/api/v4` REST/WebSocket payloads.
### Proxy logs show traffic but no `latest.md`
The mirror writes files only after it sees a post payload. Startup calls such as
`/api/v4/teams`, `/api/v4/users`, `/api/v4/files`, or WebSocket ping/ack events
do not create message files. Open a channel, open a thread, scroll slightly in
history, or wait for/send a new message. Then check:
```text
ai/inbox/mattermost-mirror/latest.md
ai/inbox/mattermost-mirror/channels/<channel-name>/YYYY/MM/YYYY-MM-DD.jsonl
ai/inbox/mattermost-mirror/by-date/YYYY/MM/YYYY-MM-DD.jsonl
```