💬

CHAT

P0 · Foundation Planned · P0 design phase Owner: CPO (vacant) → interim CEO

Mattermost fork wrapped in CyberOS auth and UI shell — AI-native team chat with PGroonga Vietnamese search and Slack/Zalo import.

CHAT is the team-communication module for CyberOS. The strategy is to fork Mattermost (open-core, MIT/Apache-licensed core) for the messaging substrate and layer CyberOS-native auth (AUTH service), UI shell (Tauri desktop + mobile shell), search (PGroonga for Vietnamese full-text), and AI-native features (thread summarisation via /summarise, smart-reply suggestions, daily digest, mention-aware answers from Genie) on top. Channels, threads, file attachments, reactions, voice messages, Slack import, Zalo import where API allows — all the table-stakes plus an offline-first sync engine (Yjs CRDT) for desktop draft editing. PRD §9.3 specifies the 12 FRs; §11.2.2 sets the availability target (≥ 99.9%); §11.2.1 sets the message-deliver p95 (≤ 200 ms). PDPL Art. 14 DSAR is satisfied by per-subject message export.

CHAT is the internal team-communication module, layered on a Mattermost fork that provides battle-tested messaging primitives (channels, threads, attachments, reactions, presence, mobile push). On top of that fork, CyberOS adds: a native auth bridge to the AUTH service (no separate Mattermost user database), a Tauri-based desktop + mobile shell that matches the rest of CyberOS, PGroonga as the full-text engine (for Vietnamese tokenisation — measured recall ≥ 80% on a public VN test set), a Slack/Zalo import path, AI-native features driven by the AI Gateway (@genie inline mentions, /summarise thread compactions, smart-reply, daily digest), an offline draft sync engine using Yjs CRDT, and a BRAIN bridge that streams every message into Layer 3 of memory within p95 ≤ 5 s. The compliance export reuses Mattermost's format plus the CyberOS audit chain anchor — so regulators see one bundle.

Status
Planned
P0 · design phase · M+2
Strategy
Fork Mattermost
open-core · MIT/Apache
Search engine
PGroonga
VN tokeniser · recall ≥ 80%
Send p95
≤ 200 ms
N(FR pending)
Availability
≥ 99.9%
N(FR pending)
BRAIN ingest p95
≤ 5 s
(FR pending)
Desktop / mobile
Tauri
offline-first via Yjs
Voice ASR
Whisper-large-v3
self-hosted · VN + EN
1

Why CHAT exists

Building a chat server from scratch is months of work whose differentiator (CyberOS auth, AI features, Vietnamese search, BRAIN bridge) is at the edges, not the middle. Mattermost has solved channels, threads, attachments, presence, mobile push, federation, and admin tooling at production quality. Forking it lets the CyberOS team focus on the differentiators while keeping a vendor-independent path (no Mattermost SaaS dependency, no per-seat fee).

🏗
Don't rebuild the wheel

Mattermost has years of production hardening on the messaging core. Forking + integrating lets us ship in months not years.

🇻🇳
Vietnamese-first

PGroonga (with TinySegmenter and VietBERT-derived rules) gives the Vietnamese tokenisation the upstream lacks. Search recall ≥ 80% on the public VN test set.

🧠
AI is a feature, not a bolt-on

@genie inline mentions, /summarise threads, smart-reply, daily digest — all driven by the AI Gateway, persona-stamped, audit-chained.

The bet: take the part Mattermost did well (the messaging substrate), wrap it in the parts CyberOS does well (auth, audit, AI, Vietnamese), and ship a chat product that feels like Slack-quality and is end-to-end ours.

2

What it does — 5W1H2C5M

AxisQuestionAnswer
5W · WhatWhat is CHAT?A team-chat module. Mattermost-derived core + CyberOS auth/UI/search/AI plug-ins. Channels (public + private + DM), threads, file attachments, reactions, mentions, voice messages, smart replies, daily digest, Slack/Zalo import, compliance export.
5W · WhoWho uses it?Members of a tenant (team chat). Genie (@genie mention → AI answer with citations). CUO digest bot (morning brief). Alert bots (#cyberos-alerts from OBS). Owner: CPO seat.
5W · WhenWhen does it run?24/7. Hot push for online members; FCM/APNs for mobile when offline. BRAIN ingest within 5 s of message create.
5W · WhereWhere does it run?Fargate task (Go core from Mattermost) + Postgres + Redis + MinIO/S3 for attachments. Per-region; SG-1 at P0.
5W · WhyWhy a separate module?Because chat is the highest-bandwidth surface between humans + AI; co-locating it with the platform unlocks audit, search, and AI features the SaaS world can't match.
1H · HowHow does it work?Browser/desktop/mobile clients hit the CyberOS API gateway. CHAT service serves messages via WebSocket + HTTP. Postgres stores messages, channels, users (synced from AUTH). PGroonga indexes content with VN tokenisation. AI features call AI Gateway. BRAIN bridge tails the Postgres logical replication slot and streams messages into BRAIN's Layer 3 corpus.
2C · CostCost?P0: ~$45/month (Fargate + RDS small). 50-tenant: ~$280/month (Fargate scale-out + Redis cluster + MinIO).
2C · ConstraintsConstraints?(a) PGroonga tokenisation must hit ≥ 80% recall on VN test set. (b) Send p95 ≤ 200 ms. (c) Per-channel ACL enforced; DMs namespace-isolated in BRAIN. (d) PDPL Art. 14 DSAR — full message export per subject.
5M · MaterialsStack?Go (Mattermost-derived) · PostgreSQL 16 + PGroonga · Redis 7 (presence + push fanout) · MinIO (attachments, S3-compatible) · Tauri (desktop + mobile shell) · Yjs CRDT (offline drafts) · Whisper-large-v3 (ASR) · AI Gateway (summarisation, smart-reply).
5M · MethodsMethod choices?WebSocket for hot push; long-poll fallback. Logical replication slot to BRAIN. PGroonga full-text index per channel. CRDT for offline draft sync. ASR runs locally on a shared GPU pod.
5M · MachinesDeployment?Fargate (Go service · 2 CPU · 4 GB). RDS Postgres 16. Redis 7. MinIO on EBS-backed volumes.
5M · ManpowerWho maintains?0.3 FTE CPO + 0.5 FTE CTO at P0. P1+: 1 FTE PM + 1 FTE FE eng + ongoing.
5M · MeasurementHow measured?N(FR pending) (send p95 ≤ 200 ms), N(FR pending) (availability ≥ 99.9%), (FR pending) (VN search recall ≥ 80%), (FR pending) (BRAIN ingest p95 ≤ 5 s).
3

Architecture

Three layers stacked. Substrate: Mattermost-derived Go service (channels, threads, attachments, presence, push). Native CyberOS layer: auth bridge, UI shell (Tauri), PGroonga search adapter, BRAIN bridge, voice ASR. AI layer: Genie agent, summarisation, smart-reply, daily digest — all calling AI Gateway.

graph TB subgraph CLIENTS ["Clients (Tauri shell)"] DT["Desktop (Tauri)"] MOB["Mobile (Tauri / WebView)"] WEB["Browser SPA"] end subgraph CHAT ["CHAT service (Go · Mattermost fork)"] WS["websocket.go
hot push"] API["api.go
HTTP + GraphQL"] CHAN["channels.go
public · private · DM"] THR["threads.go
reply chains"] MSG["messages.go
create · update · delete"] PRES["presence.go
online/away/dnd"] NOTIF["notifications.go
FCM + APNs fanout"] end subgraph CYBER ["CyberOS native plug-ins"] AUTHB["auth_bridge.go
JWT verify + RBAC.Check"] SEARCH["search.go
PGroonga adapter · VN tokenise"] BRAINB["brain_bridge.go
logical replication tail"] IMP["importers/
slack · zalo"] ASR["asr_client.go
Whisper gRPC"] YJS["yjs_sync.go
CRDT draft sync"] end subgraph AI ["AI features"] GENIE["genie.go
@genie mention handler"] SUMM["summarise.go
/summarise thread"] SREPLY["smart_reply.go
3 suggestions / mention"] DIG["digest.go
daily channel digest"] end subgraph STORES PG[("PostgreSQL 16
+ PGroonga
messages · channels
RLS by tenant_id")] REDIS[("Redis 7
presence + push fanout")] MINIO[("MinIO (S3-compatible)
attachments")] end subgraph EXT ["External CyberOS services"] AUTH["🔐 AUTH"] AIGW["🧠 AI Gateway"] BRAIN["🧠 BRAIN"] OBS["👁 OBS"] GPU["Whisper GPU pod"] end DT --> WS DT --> API MOB --> WS MOB --> API WEB --> WS WEB --> API API --> AUTHB WS --> AUTHB AUTHB --> AUTH API --> CHAN API --> THR API --> MSG MSG --> PG CHAN --> PG THR --> PG WS --> PRES PRES --> REDIS MSG --> NOTIF NOTIF --> REDIS API --> SEARCH SEARCH --> PG MSG --> BRAINB BRAINB --> BRAIN MSG --> GENIE THR --> SUMM MSG --> SREPLY GENIE --> AIGW SUMM --> AIGW SREPLY --> AIGW DIG --> AIGW API --> IMP WS --> YJS YJS --> PG MSG --> ASR ASR --> GPU CHAT --> OBS classDef planned fill:#ecfdf5,stroke:#45210e classDef store fill:#f5f3ff,stroke:#7c3aed classDef ext fill:#fef6e0,stroke:#9c750a class WS,API,CHAN,THR,MSG,PRES,NOTIF,AUTHB,SEARCH,BRAINB,IMP,ASR,YJS,GENIE,SUMM,SREPLY,DIG,DT,MOB,WEB planned class PG,REDIS,MINIO store class AUTH,AIGW,BRAIN,OBS,GPU ext

Internal components

ComponentPath (planned)Responsibility
websocket.goservices/chat/server/websocket.goPersistent WS connection per client. Routes incoming events (typing, presence) and pushes outgoing (new message, mention, reaction).
api.goservices/chat/server/api.goHTTP REST + GraphQL endpoints. OpenAPI documented; deprecation policy quarterly.
channels.goservices/chat/server/channels.goCRUD on channels. Per-channel ACL: public, private (member-of), DM (1:1), group-DM (≤ 8).
threads.goservices/chat/server/threads.goReply chains. Notifies thread followers; surfaces in unread tray.
messages.goservices/chat/server/messages.goSend · edit · delete · pin · react. Mention parsing (@user, #channel, @genie).
presence.goservices/chat/server/presence.goOnline · away · DND. Redis-backed; TTL-refresh from WS heartbeats.
notifications.goservices/chat/server/notifications.goFanout: in-app, FCM (Android), APNs (iOS), email digest.
auth_bridge.goservices/chat/native/auth_bridge.goReplaces Mattermost native auth. Verifies CyberOS JWT; resolves subject; calls AUTH RBAC for channel ACLs.
search.goservices/chat/native/search.goPGroonga adapter. VN-tokeniser config; recall measured against test set.
brain_bridge.goservices/chat/native/brain_bridge.goTails Postgres logical-replication slot. Streams new messages into BRAIN Layer 3 corpus within p95 ≤ 5 s.
importers/slack.goservices/chat/native/importers/slack.goSlack Workspace export → CyberOS channels + messages. Preserves threads, attachments, reactions.
importers/zalo.goservices/chat/native/importers/zalo.goZalo OA API import (where API allows). Mapping limited by Zalo API surface.
asr_client.goservices/chat/native/asr_client.goVoice-message ASR via Whisper-large-v3 (self-hosted L4 GPU pod). VN + EN.
yjs_sync.goservices/chat/native/yjs_sync.goYjs CRDT-based offline draft sync. Draft conflicts resolved per CRDT rules.
genie.goservices/chat/ai/genie.go@genie mention handler. Builds context from thread + channel; calls AI Gateway; posts answer with citations.
summarise.goservices/chat/ai/summarise.go/summarise slash command. Thread → summary with TL;DR and action items.
smart_reply.goservices/chat/ai/smart_reply.goOn every @-mention to a user, generate 3 reply suggestions (latency p95 ≤ 1.4 s, (FR pending)).
digest.goservices/chat/ai/digest.goDaily channel digest ((FR pending)) for members in "Notify" mode.
tauri_shell/services/chat/tauri/Tauri Rust shell. Desktop (macOS · Windows · Linux) + mobile (iOS · Android via Tauri 2.0 mobile).
4

Data model

Postgres-backed. Schema follows the Mattermost shape with CyberOS-specific extensions for audit linkage and BRAIN ingest watermarks. All tables RLS-scoped by tenant_id.

erDiagram TENANT ||--o{ CHANNEL : "owns" TENANT ||--o{ USER_REF : "synced from AUTH" USER_REF ||--o{ MEMBERSHIP : "joins" CHANNEL ||--o{ MEMBERSHIP : "has" CHANNEL ||--o{ MESSAGE : "contains" MESSAGE ||--o{ REACTION : "receives" MESSAGE ||--o{ MENTION : "carries" MESSAGE ||--o{ ATTACHMENT : "has" MESSAGE ||--o| AUDIT_LINK : "links to BRAIN row" CHANNEL ||--o{ ACL_RULE : "scoped by" USER_REF ||--o{ PRESENCE : "current" IMPORTED_BUNDLE ||--o{ MESSAGE : "imported from" CHANNEL { uuid id PK uuid tenant_id FK string slug string kind "public or private or direct or group_direct" string display_name string purpose timestamp created_at string brain_corpus_slot "memories-chat-channel path" } USER_REF { uuid id PK uuid auth_subject_id FK uuid tenant_id FK string display_name string locale "vi-VN or en-US or other" } MEMBERSHIP { uuid channel_id FK uuid user_id FK string role "owner or admin or member or guest" timestamp joined_at timestamp last_read_at string notify_mode "all or mention or quiet or digest" } MESSAGE { uuid id PK uuid channel_id FK uuid parent_id "FK to MESSAGE thread root - self-reference" uuid author_id FK string body obj blocks "rich content" timestamp created_at timestamp edited_at timestamp deleted_at bigint brain_ingest_seq string brain_chain string source "native or slack_import or zalo_import" } REACTION { uuid id PK uuid message_id FK uuid user_id FK string emoji timestamp ts } MENTION { uuid id PK uuid message_id FK string target "user-uuid or channel-uuid or genie" } ATTACHMENT { uuid id PK uuid message_id FK string filename string content_type bigint size_bytes string s3_key string transcript "voice note ASR" } ACL_RULE { uuid id PK uuid channel_id FK string scope "role or user" string code "founder or member or other" string action "read or write or invite or archive" } PRESENCE { uuid user_id PK string status "online or away or dnd" timestamp last_seen_at } AUDIT_LINK { uuid message_id FK bigint brain_seq string brain_chain } IMPORTED_BUNDLE { uuid id PK string source "slack or zalo" timestamp imported_at int message_count obj manifest }

Channel kinds + ACL rules

KindVisibilityDefault ACLBRAIN slot
publicAll members of tenanteveryone read · channel members writecompany:
privateMember-of onlymembers read+write; admin managesmodule:chat:private:
direct (DM)1:1both parties read+writemember::dm:
group_direct≤ 8 membersall members read+writemodule:chat:group:
5

API surface

GraphQL subgraph (federated)

extend schema
  @link(url: "https://specs.apollo.dev/federation/v2.5", import: ["@key", "@requiresScopes"])

type Channel @key(fields: "id") {
  id: ID!
  slug: String!
  kind: ChannelKind!
  displayName: String!
  purpose: String
  members: [Membership!]! @requiresScopes(scopes: [["chat.read"]])
  recentMessages(limit: Int = 50): [Message!]! @requiresScopes(scopes: [["chat.read"]])
}

type Message @key(fields: "id") {
  id: ID!
  channelId: ID!
  authorId: ID!
  body: String!
  blocks: JSON
  parentId: ID
  createdAt: DateTime!
  editedAt: DateTime
  reactions: [Reaction!]!
  attachments: [Attachment!]!
  brainChain: String                # links to BRAIN audit row
}

type Reaction { emoji: String!  userId: ID!  ts: DateTime! }

type Attachment {
  id: ID!
  filename: String!
  contentType: String!
  sizeBytes: Int!
  url: String!
  transcript: String                # voice notes only
}

type Membership {
  user: User!
  role: MembershipRole!
  notifyMode: NotifyMode!
  lastReadAt: DateTime
}

enum ChannelKind { PUBLIC PRIVATE DIRECT GROUP_DIRECT }
enum MembershipRole { OWNER ADMIN MEMBER GUEST }
enum NotifyMode { ALL MENTION QUIET DIGEST }

type Query {
  channel(id: ID!): Channel
  channels(kind: ChannelKind): [Channel!]!
  searchMessages(q: String!, channelId: ID, limit: Int = 50): [Message!]!
}

type Mutation {
  sendMessage(channelId: ID!, body: String!, blocks: JSON, parentId: ID): Message!
  editMessage(id: ID!, body: String!): Message!
  deleteMessage(id: ID!): Boolean!
  addReaction(messageId: ID!, emoji: String!): Reaction!
  createChannel(slug: String!, kind: ChannelKind!, displayName: String!): Channel!
    @requiresScopes(scopes: [["chat.channel_create"]])
  inviteToChannel(channelId: ID!, userIds: [ID!]!): Boolean!
    @requiresScopes(scopes: [["chat.channel_invite"]])
  summariseThread(threadId: ID!): String!     # calls AI Gateway
}

type Subscription {
  channelMessages(channelId: ID!): Message!
  presenceChanges(userIds: [ID!]!): Presence!
}

WebSocket events

EventDirectionPayload
message.createdserver → clientfull Message
message.editedserver → clientMessage diff
message.deletedserver → client{id, channel_id}
reaction.addedserver → client{message_id, emoji, user_id}
typing.startedbidirectional{channel_id, user_id}
presence.changedserver → client{user_id, status}
thread.updatedserver → client{parent_id, reply_count}
smart_reply.suggestedserver → client{message_id, suggestions:[…]}

MCP tool catalogue

Tool nameInputsOutputsAnnotations
cyberos.chat.send_messagechannel_id, body, blocks?{message_id, ts}destructive=false · scope=chat.write
cyberos.chat.search_messagesq, channel_id?, limit?Message[]readOnly=true · scope=chat.read
cyberos.chat.summarise_threadthread_id{summary, action_items}readOnly=true · scope=chat.read
cyberos.chat.list_channelsChannel[]readOnly=true · scope=chat.read
cyberos.chat.create_channelslug, kind, nameChanneldestructive=false · scope=chat.channel_create
cyberos.chat.invitechannel_id, user_ids[]{ok}destructive=false · scope=chat.channel_invite
cyberos.chat.export_dsarsubject_id, since?{zip_url}destructive=false · scope=chat.dsar_export
6

Key flows

Flow 1 — Send message (mention fanout + BRAIN ingest)

sequenceDiagram autonumber participant U as User (desktop) participant WS as CHAT websocket participant API as CHAT api participant AUTH as 🔐 AUTH RBAC participant PG as Postgres + PGroonga participant NOT as notifications participant BB as brain_bridge participant BR as 🧠 BRAIN participant FCM as FCM/APNs U->>WS: send message {channel, body, mentions:[@bao, @genie]} WS->>AUTH: RBAC.Check(chat.write, channel) AUTH-->>WS: allow WS->>API: persist API->>PG: INSERT message, mentions, etc. PG-->>API: row id API->>NOT: fanout {mentioned:[bao], followers:[…]} NOT->>WS: push to online users (channel.members) NOT->>FCM: push to offline users par BRAIN ingest (async, p95 ≤ 5s) PG-->>BB: logical replication event BB->>BR: put memories/chat//.md BR-->>BB: {seq, chain} BB->>PG: UPDATE brain_chain on message and Genie answer (if mention) NOT->>WS: trigger @genie handler end

(FR pending): BRAIN ingest p95 ≤ 5 s. Logical replication is the load-bearing piece — Postgres ships the WAL, the bridge transforms each row into a BRAIN put.

Flow 2 — Thread reply

sequenceDiagram autonumber participant U as User participant WS as websocket participant API as api participant PG as Postgres U->>WS: send {parent_id:, body} WS->>API: persist as reply API->>PG: INSERT message WHERE parent_id= PG-->>API: row + thread.reply_count++ API->>WS: thread.updated event to followers WS-->>U: ack with thread_id Note over WS: followers root + repliers get desktop badge plus unread tray entry

Flow 3 — Vietnamese search (PGroonga)

sequenceDiagram autonumber participant U as User participant API as api participant S as search.go (PGroonga adapter) participant PG as Postgres + PGroonga participant AUTH as RBAC U->>API: GET /api/v1/search?q="hợp đồng singapore" API->>AUTH: RBAC.Check(chat.read, *) AUTH-->>API: allow API->>S: search(q, user_scope) S->>S: tokenise VN ("hợp đồng singapore" → [hợp_đồng, singapore]) S->>PG: SELECT … WHERE body @@ tokens AND channel_id IN (membership) PG-->>S: matching rows (with snippet highlights) S-->>API: 23 hits API-->>U: results

(FR pending): PGroonga VN tokeniser; recall ≥ 80% on the public VN test set. Membership filter applied first to enforce ACL.

Flow 4 — Thread summarisation (/summarise)

sequenceDiagram autonumber participant U as User participant API as api participant SUM as summarise.go participant AI as 🧠 AI Gateway participant PG as Postgres U->>API: slash command "/summarise" API->>SUM: thread_id SUM->>PG: SELECT messages WHERE parent_id= ORDER BY created_at PG-->>SUM: 47 messages SUM->>SUM: build context, redact PII names SUM->>AI: ChatComplete(persona="genie", model=auto, messages=…) AI-->>SUM: summary + action items SUM->>API: render as inline reply API-->>U: "TL;DR: … Action items: …"

(FR pending): thread summarisation p95 ≤ 3 s. Most cost in AI Gateway call; CHAT adds ~80 ms overhead.

Flow 5 — Slack import

sequenceDiagram autonumber participant ADMIN as Tenant admin participant CLI as cyberos-chat import participant IMP as importers/slack.go participant PG as Postgres participant BB as brain_bridge participant BR as 🧠 BRAIN ADMIN->>CLI: cyberos-chat import slack --bundle slack-export.zip CLI->>IMP: parse bundle IMP->>IMP: enumerate channels, users, messages Note over IMP: 142 channels · 8,420 users · 1.4M messages loop per channel IMP->>PG: INSERT channel IMP->>PG: INSERT messages (batched 500) PG-->>IMP: rows IMP->>BB: trigger backfill ingest BB->>BR: put memories/chat//... end IMP-->>CLI: done CLI-->>ADMIN: report (channels, messages, attachments transferred)

(FR pending): Slack import path; Zalo where API allows. Backfill BRAIN ingest is throttled to avoid swamping the chain (max 1k ops/sec).

7

Message lifecycle

A single message traverses up to seven states from draft to BRAIN ingest. Edits + deletes are soft; the BRAIN audit row remains.

stateDiagram-v2 [*] --> Drafting: user typing (Yjs CRDT if offline) Drafting --> Sending: user hits enter / send button Sending --> Persisted: Postgres INSERT Persisted --> Fanned: WebSocket + FCM/APNs delivery Fanned --> Acknowledged: clients render Persisted --> BRAINIngested: logical replication → BRAIN put Acknowledged --> Edited: user edits Edited --> Persisted: UPDATE on message Acknowledged --> Reacted: emoji added Acknowledged --> Threaded: reply created (separate message) Acknowledged --> Deleted: soft-delete (deleted_at set) Deleted --> Purged: DSAR purge or retention expiry BRAINIngested --> [*] Purged --> [*]

Notify-mode behaviour

ModeWhen notifiedChannel
allevery new messagedesktop + mobile push
mention@self or @channel or @heredesktop + mobile push
quietonly @selfdesktop only
digestdaily digest summaryemail + in-app inbox
8

Functional Requirements

The CyberOS FR catalogue is being rebuilt one feature at a time via the open fr-author Agent Skill.

Previous FR enumerations were archived 2026-05-14 and are no longer reflected on this page. PRD/SRS narrative remains authoritative for the spec; specific FRs land here as they are re-authored.

9

Non-Functional Requirements

NFR IDConcernTargetMeasurement
N(FR pending)CHAT message-deliver p95≤ 200 msWebSocket round-trip · k6
N(FR pending)CHAT availability (28-day)≥ 99.9%SLO
N(FR pending)Thread summarisation p95≤ 3 s(FR pending) test
N(FR pending)Smart-reply suggestion p95≤ 1.4 s(FR pending)
N(FR pending)VN search query p95≤ 250 ms over 1M messagesk6 search test
N(FR pending)BRAIN ingest end-to-end p95≤ 5 s(FR pending)
N(FR pending)VN search recall on test set≥ 80%(FR pending)
N(FR pending)VN search precision on test set≥ 85%(FR pending) test
N(FR pending)Concurrent WS connections (P0)≥ 5,000load test
N(FR pending)Messages / second (P0)≥ 500k6 sustained
N(FR pending)DSAR export completeness100% messages + reactions + attachmentsfixture test
N(FR pending)Message → BRAIN audit link rate100% (no dropped messages)continuous reconciliation
N(FR pending)P0 infra cost≤ $45/monthOBS cost dashboard
10

Dependencies

graph LR subgraph upstream ["CHAT depends on"] AUTH["🔐 AUTH
JWT + RBAC
+ user sync"] BRAIN["🧠 BRAIN
message corpus
(Layer 3)"] AIGW["🧠 AI Gateway
genie · summarise · smart-reply"] OBS["👁 OBS
traces + metrics"] PG["🗄 Postgres
+ PGroonga"] REDIS["⚡ Redis
presence + push"] S3["☁️ MinIO/S3
attachments"] GPU["Whisper GPU
voice ASR"] end CHAT["💬 CHAT"] subgraph consumers ["CHAT used by"] CUO["🎯 CUO digest"] SK["🛠 Skill (bot mentions)"] OBS2["👁 OBS alert bot"] USERS["End users"] end AUTH --> CHAT BRAIN --> CHAT AIGW --> CHAT OBS --> CHAT PG --> CHAT REDIS --> CHAT S3 --> CHAT GPU --> CHAT CHAT --> CUO CHAT --> SK CHAT --> OBS2 CHAT --> USERS classDef shipped fill:#f5ede6,stroke:#45210e classDef planned fill:#ecfdf5,stroke:#45210e class BRAIN,SK shipped class CHAT,AUTH,AIGW,OBS,CUO,OBS2,USERS planned class PG,REDIS,S3,GPU planned
11

Compliance scope

Regulation / standardArticle / clauseCHAT feature
Vietnam PDPL (Law 91/2025)Art. 14 — DSARPer-subject message export via cyberos-chat export-dsar.
Vietnam PDPLArt. 16 — ErasureSoft-delete + BRAIN audit-row purge; chain row preserved.
Vietnam Decree 13/2023Art. 17 — Processing logEvery message → BRAIN row; chain provides processing log.
Vietnam Decree 53/2022Art. 26 — Data residencyPer-tenant residency tag honoured by RDS region selection.
GDPRArt. 17 — Right to erasureDSAR purge; BRAIN audit fact remains.
GDPRArt. 32 — Security of processingTLS in transit, AES-256-GCM at rest, per-channel ACL.
EU AI ActArt. 12 — LoggingGenie answers + summaries land in BRAIN with persona-version.
EU AI ActArt. 13 — Transparency@genie answers carry "AI-generated" label + citations.
ISO/IEC 27001:2022A.5.30 — ICT readinessBRAIN bridge provides off-cluster message replica.
ISO/IEC 27001:2022A.8.5 — Secure authenticationAUTH service handles all logins; no Mattermost native auth.
SOC 2 Type IICC6.1 — Logical accessPer-channel ACL via AUTH RBAC.
SOC 2 Type IICC7.2 — MonitoringOBS SLO dashboards for CHAT availability + latency.
12

Risk entries

IDRiskLikelihoodImpactOwnerMitigation
R-CHAT-001Mattermost upstream license change breaks forkLowHighCPOFork at known-MIT/Apache version; back-port security patches only; ongoing legal review.
R-CHAT-002BRAIN ingest backlog → messages "missing" from searchMediumMediumCTOSLO: ingest p95 ≤ 5 s. Alerting on backlog > 60 s. Logical replication slot monitoring.
R-CHAT-003VN tokeniser regression below 80% recallMediumMediumCPOCI test on public VN test set; PGroonga config under version control; quarterly review.
R-CHAT-004Cross-channel message leak via crafted GraphQL queryLowHighCSORBAC enforced at API; cross-channel property-based test in CI.
R-CHAT-005@genie injection — user hides instructions in message bodyMediumMediumCSOSystem prompt at AI Gateway level (not in CHAT); content-safety filter; CaMeL enforcement.
R-CHAT-006Voice-message ASR transcript inaccurate → wrong context for @genieMediumLowCPOWhisper-large-v3 self-hosted; user can edit transcript pre-send.
R-CHAT-007Slack import drops threads / reactionsMediumLowCPOImporter test fixtures cover thread + reaction + attachment paths; manifest validates before write.
R-CHAT-008WebSocket connection limit hit at scaleMediumMediumCTOP0 budget: 5k concurrent. Horizontal scale-out via Redis pub-sub for fanout at P1+.
R-CHAT-009Mobile draft sync conflict produces double-postLowMediumCPOYjs CRDT semantics + send-once token on submit.
R-CHAT-010Compliance export omits CyberOS audit anchorLowMediumCLOExport test verifies BRAIN chain hashes for every message in bundle.
13

KPIs

KPIFormulaSourceTarget
Send p95 latencyhistogramOBS≤ 200 ms
Availability (28d)1 − error_minutes / totalOBS SLO≥ 99.9%
BRAIN ingest p95histogrambrain_bridge metrics≤ 5 s
VN search recallTP / (TP + FN)CI test set≥ 80%
VN search query p95histogramOBS≤ 250 ms
@genie usage (DAU)distinct subjects / daychat eventstracked; ≥ 60% of users
Concurrent WS connections (peak)gaugeOBS≤ N(FR pending) (5k P0)
Message volume / day (tenant)countOBStracked for capacity planning
DSAR fulfilment timerequest → export deliveredrequest tracker≤ 24 h
14

RACI matrix

ActivityCEOCPOCTOCDOCSODPO
Product spec + UXARCIII
Implementation (Go fork + plugins)IARIII
VN search tokeniser tuningICCA/RII
BRAIN bridge integrationICRAII
AI feature integration (genie, summarise, smart-reply)ARCCII
Slack/Zalo importersIA/RCIII
Compliance export (DSAR)ICCRCA
Mobile app (Tauri)IA/RCIII
15

Planned CLI surface

Operator CLI cyberos-chat for admin tasks. Members interact via the GUI shell.

1. List channels

$ cyberos-chat channels list --tenant acme

SLUG                  KIND      MEMBERS  MESSAGES  LAST_ACTIVITY
general               public    42       18,420    2026-05-14T07:21Z
engineering           public    18       9,420     2026-05-14T07:19Z
hanoi-office          public    12       3,210     2026-05-14T06:45Z
ceo-stephen-vy        direct    2        412       2026-05-14T05:33Z
project-alpha         private   8        2,847     2026-05-14T07:02Z

2. Send a message via CLI (for automation)

$ cyberos-chat send --channel engineering --body "Deploy v0.9.2 starting at 14:00 VN. Watch #cyberos-alerts."

[sent]   message_id=msg_01HZJ…XK · channel=engineering · ts=2026-05-14T07:22:08Z
[brain]  ingest queued · expected p95 ≤ 5 s

3. Search Vietnamese content

$ cyberos-chat search "hợp đồng Singapore HoldCo"

[search]  channel=engineering  3 hits  recall_est=87%
msg_01HZG…   2026-05-12  stephen@: "đang draft hợp đồng Singapore HoldCo, deadline T5"
msg_01HZH…   2026-05-13  bao@: "đã review hợp đồng, comment đã gửi"
msg_01HZI…   2026-05-14  stephen@: "Singapore HoldCo flip nếu ARR ≥ $1.5M"

4. Import Slack workspace

$ cyberos-chat import slack --bundle slack-export.zip --tenant acme

[parse]   142 channels · 8,420 users · 1.4M messages · 32k attachments
[map]     user mapping: 8,420 → 8,420 (zero unmapped)
[backfill] 142 channels created
[ingest]  142,000 messages / hour (throttled to BRAIN ingest budget)
[done]    elapsed 9h 47m · all messages backfilled to BRAIN
[verify]  random sample: 100/100 round-trip ok

5. DSAR export

$ cyberos-chat export-dsar --subject acme-contact@acme.com --output dsar-chat.zip

[export]  subject: acme-contact@acme.com
[export]  channels: 14 (12 public, 2 DM)
[export]  messages: 4,217
[export]  attachments: 142 (1.4 GB total)
[export]  reactions: 1,032
[export]  brain_anchor: included (audit chain hashes per message)
[written] dsar-chat.zip · 1.5 GB

6. Summarise a thread (operator-side)

$ cyberos-chat summarise-thread --id thr_01HZJ…XK

TL;DR: The team is debating whether to ship feature-X with the experimental
       summariser or hold for v2 of the prompt. Stephen leans ship-it; Bao
       wants one more A/B test.
Action items:
  • Bao: prepare A/B comparison by Wed 2026-05-15
  • Stephen: review prompt v2 draft
  • Both: align on go/no-go at the Friday standup

7. Health + SLO

$ cyberos-chat health

availability_28d:     99.96%  ✓ (target ≥ 99.9%)
send_p95_ms:          142     ✓ (target ≤ 200)
brain_ingest_p95_s:   3.2     ✓ (target ≤ 5)
vn_search_recall:     0.87    ✓ (target ≥ 0.80)
ws_connections_now:   1,124
messages_today:       18,420
16

Phase status & estimates

Status
Planned
P0 · design phase · M+2
Est. LoC (CyberOS plugins)
~12,000
Go + Rust shell + Tauri
Mattermost fork base
v9.x LTS
MIT/Apache core
Planned tests
200+
incl. VN search recall fixtures
P0 monthly cost
~$45
Fargate + RDS small + Redis + MinIO
CLI commands
~20 planned
cyberos-chat
CapabilityStatus
Mattermost fork + auth_bridge to AUTHplanned · P0
Channels (public, private, DM, group-DM)planned · P0
Threads, reactions, attachmentsplanned · P0
PGroonga VN searchplanned · P0
BRAIN bridge (logical replication)planned · P0
@genie inline mentionplanned · P0
/summarise thread commandplanned · P0
Slack importplanned · P0
Tauri desktop shell (mac · win · linux)planned · P0
DSAR exportplanned · P0
Smart-reply suggestionsplanned · P1
Daily digest (notify=digest mode)planned · P1
Voice messages + Whisper ASRplanned · P1
Zalo import (where API permits)planned · P1
Mobile app (Tauri 2.0 mobile)planned · P3
Yjs CRDT offline draft syncplanned · P3
Multi-region active-activeplanned · P3+
17

References

  • PRD §9.3 — CHAT module specification + (FR pending) through (FR pending).
  • PRD §11.2.1 — N(FR pending) (CHAT message-deliver p95 ≤ 200 ms).
  • PRD §11.2.2 — N(FR pending) (CHAT availability ≥ 99.9%).
  • SRS §4.3 — Formal (FR pending) catalogue with verification methods.
  • Mattermost upstream — open-core MIT/Apache messaging substrate.
  • PGroonga — Postgres full-text extension with VN tokenisation support.
  • Yjs — CRDT library for offline draft sync.
  • Tauri 2.0 — Rust-based desktop + mobile shell.
  • Whisper-large-v3 — self-hosted ASR for VN + EN voice messages.
  • Vietnam PDPL (Law 91/2025) — Art. 14 DSAR.
  • EU AI Act — Art. 12 logging, Art. 13 transparency (AI label on @genie answers).
  • Architecture context: runtime.html#chat.