🤝

CRM

P1 · Internal productivity Planned · P1 design phase Owner: CRO seat (interim CEO)

Vietnamese-market-first client management — Account / Contact / Deal with MST validation, VietQR collection, hóa đơn generation, and Vietnamese-aware salutation logic baked into every contact field.

CRM is the customer-facing memory and pipeline. Three primitives — Account, Contact, Deal — with customisable pipelines, configurable stages, and per-deal probability + expected close date for forecasting. Activities (calls, emails, meetings, notes) feed from CHAT, EMAIL, and Calendar automatically. The Vietnamese-specific bits matter: account types map to legal entity kinds (Sole proprietor / LLC / JSC / FDI), MST tax codes are validated through the vn-mst-validate skill against the GDT registry, the vn-bank-transfer skill generates VietQR codes for invoice collection, and vn-vat-invoice issues the hóa đơn on deal close. AI features: lead scoring, next-best-action suggestions, win/loss analysis after a deal closes. PRD §9.11.

CRM is CyberOS's customer pipeline, account intelligence, and Vietnamese-market commercial layer. The data model is Salesforce-flavoured (Account → Contact → Deal) but the integrations bake in Vietnamese specifics: vn-mst-validate verifies a tax code against the General Department of Taxation registry; vn-bank-transfer generates a Napas247 / VietQR code so a deal can request collection with one tap; vn-vat-invoice emits the hóa đơn directly on deal close. Pipelines are workspace-configurable (sales / partner / inbound / outbound shapes) with custom transition rules. Activities — calls, emails, meetings, notes — appear automatically: EMAIL auto-logs inbound/outbound for tracked domains, CHAT logs meeting notes, Calendar logs meeting attendance. CUO/CRO-skill produces lead scoring, next-best-action, and confidence-banded forecasts. PRD §9.11.

Status
Planned
P1 · design phase
Primitives
3
Account · Contact · Deal
Pipeline
Custom
stages + transition rules
VN skills
3 native
MST · VietQR · hóa đơn
Activity feeds
CHAT · EMAIL · Cal
auto-logged
AI features
3
score · NBA · forecast
Depends on
AUTH · BRAIN · EMAIL
+ AI · MCP · INV · Skills
Est. LoC
~8,500
Rust + TS pipeline UI
1

Why CRM exists

Off-the-shelf CRMs (Salesforce, HubSpot, Pipedrive) work, but they do not natively model Vietnamese commercial realities. MST validation requires a custom integration; VietQR generation needs a separate plugin; hóa đơn generation almost always lands as a third-party Misa or Viettel-eInvoice connector that breaks on every release. Building CRM as a CyberOS module means these become first-class: the vn-mst-validate skill is invoked on every Account write, the vn-bank-transfer skill is one click away on every Deal, and vn-vat-invoice fires automatically on deal close into INV. Beyond the VN specifics, CyberOS-native CRM benefits from the audit chain (every stage transition is a BRAIN row), the agent-equal model (CUO can log activities just like a Member), and tight coupling to PROJ (a closed deal becomes an Engagement, no manual re-keying).

🇻🇳
Vietnamese-first

MST, VietQR, hóa đơn, Anh/Chị salutation, address-parsing helpers — built in, not bolted on.

🪢
Activity auto-log

Inbound / outbound emails to tracked domains, calendar attendance, CHAT meeting notes — all appear in the activity timeline without manual entry.

🔮
AI forecasting + NBA

CUO/CRO-skill produces confidence-banded forecasts and concrete next-best-action prompts for each open Deal.

The bet is that the Vietnamese consultancy buyer values "this works with our hóa đơn flow" more than "this has 700 SaaS integrations". Coupling CRM tightly to CyberOS skills means the VN-native flows are native, not a bolted-on plugin layer. The cost is that CyberOS owns the surface forever; the benefit is that a deal close is a one-tap event from VietQR to hóa đơn to Engagement.

2

What it does — 5W1H2C5M

A structured decomposition of CRM's scope. Every cell traces back to PRD §9.11 and §19.6.

AxisQuestionAnswer
5W · WhatWhat is CRM?An Account / Contact / Deal pipeline tracker with customisable per-pipeline stages, automatic activity feed from CHAT / EMAIL / Calendar, BRAIN-ingested closed deals, and Vietnamese-market skill integrations (MST, VietQR, hóa đơn).
5W · WhoWho uses it?Sales: create and progress deals; daily pipeline review. Account Managers: own client relationships; log activities. CRO: dashboard + forecast review. Marketing: read-only on activity + lead source. Agents: CUO/CRO-skill logs activities, suggests NBAs, produces forecasts.
5W · WhenWhen does it run?Continuous: SPA pipeline view; WebSocket on stage transitions. Hourly: activity feed reconciliation (EMAIL → CRM). Nightly: AI lead scoring refresh + win/loss analysis on closed deals. On deal close: VietQR + hóa đơn + PROJ Engagement creation.
5W · WhereWhere does it run?P1: single region (SG-1) with VN-residency RDS for VN tenants. P3+: multi-region. The CRM service is one axum binary; the pipeline UI is a React SPA component.
5W · WhyWhy a separate module?Activity volume, ACL granularity (per-deal), and Vietnamese-skill integration are too specific to belong elsewhere. Folding into PROJ corrupts both data models.
1H · HowHow does it work?Accounts are validated on write (MST → GDT registry). Contacts have a normalised phone (E.164) and email; merge candidates surface when two contacts share either. Deals carry stage, value, probability, expected close. Activities are append-only and feed from EMAIL / CHAT / Calendar with idempotency keys.
2C · CostCost budget?P1: ~$60 / month single-tenant pilot (Fargate + RDS + Redis). 50-tenant: ~$240 / month. AI lead scoring runs nightly batch; ~$0.001 per deal per night.
2C · ConstraintsConstraints?(a) Per-deal ACL — private deals not visible cross-workspace ((FR pending)). (b) Email-to-CRM auto-log only for tracked domains ((FR pending)) — never auto-attach a personal email. (c) Vietnamese-formatting helpers (Anh / Chị / Bạn) on every contact display. (d) Deals only ingested into BRAIN after closed / lost — never open pipeline data.
5M · MaterialsStack?Rust 1.81 · axum · sqlx · PostgreSQL 16 · Redis 7 · React + Zustand · vn-mst-validate skill · vn-bank-transfer skill · vn-vat-invoice skill · libphonenumber · OpenTelemetry SDK.
5M · MethodsMethod choices?Three-primitive Account / Contact / Deal (no Lead as separate primitive — Leads are Contacts with no Deal). Configurable pipeline stages (not free-form). Phone normalisation to E.164 (libphonenumber). Per-deal ACL. Idempotent activity feed (idempotency key = source event id).
5M · MachinesDeployment?Fargate axum service. RDS Postgres Multi-AZ. Redis hot cache. NATS for pipeline-event fan-out. Skill invocations via the Skill module's WASM host.
5M · ManpowerWho maintains?0.5 FTE (CRO seat) at P1 launch. By P2+: CRO owns product; CMO consulted on activity feed schema; CFO consulted on hóa đơn flow.
5M · MeasurementHow measured?Pipeline drag-drop response p95 ≤ 200 ms; activity-feed reconciliation p95 ≤ 60 s after EMAIL receipt; lead-scoring precision ≥ 70% on validated wins; deal-close → INV invoice generated within 60 s (P1: 5 min).
3

Architecture

CRM is one axum service with four surfaces (GraphQL subgraph, REST admin, MCP, WebSocket for pipeline drag-drop), three stores (Postgres canonical, Redis hot cache, NATS pipeline-event fan-out), and three Vietnamese-market skill invocations (MST validate, VietQR, hóa đơn).

graph TB subgraph CLIENT ["Clients"] SPA["SPA pipeline · contact view"] AGENT["🎯 CUO via MCP"] end subgraph EDGE ["Edge"] GQL["GraphQL subgraph"] REST["REST admin"] WS["WebSocket
pipeline drag-drop"] MCP["MCP tools"] end subgraph CORE ["CRM service (Rust)"] ACC["Account handler"] CON["Contact handler"] DEAL["Deal handler"] PIPE["Pipeline engine
(stages + rules)"] ACT["Activity feed
auto-log"] AI_SCORE["AI lead scoring"] AI_NBA["Next-best-action"] AI_FORECAST["Forecast"] MERGE["Merge candidate detector"] BRAIN_ING["BRAIN ingestor
(closed deals)"] end subgraph SKILLS ["VN-market skills"] MST["vn-mst-validate"] VQR["vn-bank-transfer
(VietQR)"] HD["vn-vat-invoice
(hóa đơn)"] end subgraph STORES ["Stores"] PG[("PostgreSQL
RLS by tenant_id
per-deal ACL")] RED[("Redis 7
WS rooms · search cache")] NATS[("NATS JetStream
pipeline events")] end subgraph SOURCES ["Activity sources"] EMAIL["✉️ EMAIL
tracked domains"] CHAT["💬 CHAT
meeting notes"] CAL["📅 Calendar
attendance"] end subgraph SINKS ["Sinks"] BRAIN["🧠 BRAIN
closed deals only"] PROJ["📋 PROJ
deal close → Engagement"] INV["🧾 INV
hóa đơn invoice"] OBS["👁 OBS"] end SPA --> WS SPA --> GQL AGENT --> MCP GQL --> ACC GQL --> CON GQL --> DEAL REST --> ACC REST --> CON REST --> DEAL MCP --> ACC MCP --> CON MCP --> DEAL WS --> PIPE ACC --> MST DEAL --> VQR DEAL --> HD HD --> INV EMAIL --> ACT CHAT --> ACT CAL --> ACT ACT --> DEAL ACT --> CON DEAL --> PIPE PIPE --> NATS NATS --> WS CON --> MERGE DEAL --> AI_SCORE DEAL --> AI_NBA DEAL --> AI_FORECAST DEAL --> BRAIN_ING BRAIN_ING --> BRAIN DEAL --> PROJ ACC --> PG CON --> PG DEAL --> PG ACT --> PG PIPE --> RED DEAL --> OBS classDef planned fill:#ffe4e6,stroke:#9f1239 classDef skill fill:#fef6e0,stroke:#9c750a classDef store fill:#f5f3ff,stroke:#7c3aed classDef sink fill:#f5ede6,stroke:#45210e class SPA,AGENT,GQL,REST,WS,MCP,ACC,CON,DEAL,PIPE,ACT,AI_SCORE,AI_NBA,AI_FORECAST,MERGE,BRAIN_ING planned class MST,VQR,HD skill class PG,RED,NATS store class BRAIN,PROJ,INV,OBS,EMAIL,CHAT,CAL sink

Internal components

ComponentPath (planned)Responsibility
account.rsservices/crm/src/account.rsAccount CRUD. MST validation on write (Vietnamese tenants). Address parser. Custom fields per workspace.
contact.rsservices/crm/src/contact.rsContact CRUD. E.164 phone normalisation. Anh / Chị / Bạn salutation derivation. Merge candidate detection.
deal.rsservices/crm/src/deal.rsDeal CRUD. Stage transitions with workflow rules. Value / probability / expected-close. Per-deal ACL.
pipeline.rsservices/crm/src/pipeline.rsPipeline definition + stage transition rules. Workspace-configurable. WebSocket fan-out on drag-drop.
activity_feed.rsservices/crm/src/activity_feed.rsAuto-log from EMAIL / CHAT / Calendar. Idempotency by source event id.
email_logger.rsservices/crm/src/email_logger.rsListens to EMAIL events; auto-logs inbound / outbound for tracked-domain mailboxes ((FR pending)).
ai_lead_scoring.rsservices/crm/src/ai_lead_scoring.rsNightly batch lead scoring. Features: activity recency, engagement size, account vertical, historical win-rate.
ai_nba.rsservices/crm/src/ai_nba.rsNext-best-action generator. For each open deal, produces a concrete suggestion ("send proposal", "schedule check-in", "request VietQR collection").
ai_forecast.rsservices/crm/src/ai_forecast.rsConfidence-banded forecast (CUO/CRO-skill). Per-pipeline VND total + USD total with 50% / 80% / 95% bands.
merge_detector.rsservices/crm/src/merge_detector.rsDetects ≥ 2 contacts sharing email or normalised phone; surfaces as a Notify ((FR pending) SRS).
vn_mst.rsservices/crm/src/vn_mst.rsAdapter to vn-mst-validate skill. Caches results 7 days.
vn_vietqr.rsservices/crm/src/vn_vietqr.rsAdapter to vn-bank-transfer skill. Generates Napas247 QR on demand.
vn_hoadon.rsservices/crm/src/vn_hoadon.rsAdapter to vn-vat-invoice skill. Fires on deal close.
brain_ingest.rsservices/crm/src/brain_ingest.rsLayer 3 ingestion of closed deals only ((FR pending)).
acl.rsservices/crm/src/acl.rsPer-deal ACL. Private deals not visible cross-workspace.
vn_salutation.rsservices/crm/src/vn_salutation.rsVietnamese salutation helper. Anh / Chị / Bạn picker from gender + age signal.
migrations/services/crm/migrations/sqlx migrations. RLS on every table.
4

Data model

Three primitives (Account, Contact, Deal) plus support tables for activities, pipelines, stages, merges, and AI outputs. Accounts carry Vietnamese-specific fields (account_type, MST). Contacts normalise phone to E.164 and persist a salutation hint. Deals carry per-deal ACL and stage transitions are audited.

erDiagram TENANT ||--o{ ACCOUNT : "owns" ACCOUNT ||--o{ CONTACT : "has" ACCOUNT ||--o{ DEAL : "has" CONTACT ||--o{ DEAL : "primary contact" DEAL ||--o{ ACTIVITY : "log" CONTACT ||--o{ ACTIVITY : "log" ACCOUNT ||--o{ ACTIVITY : "log" DEAL ||--o| PIPELINE : "lives in" PIPELINE ||--o{ STAGE : "has" DEAL ||--o| STAGE : "currently at" DEAL ||--o{ STAGE_TRANSITION : "history" DEAL ||--o| LEAD_SCORE : "scored" DEAL ||--o| NBA_SUGGESTION : "advised" DEAL ||--o| VIETQR : "collection" DEAL ||--o| HOA_DON : "invoice" CONTACT ||--o{ CONTACT_MERGE_CANDIDATE : "candidate" DEAL ||--o| DEAL_ACL : "private" TENANT { uuid id PK string slug } ACCOUNT { uuid id PK uuid tenant_id FK string name string account_type "sole_proprietor | llc | jsc | fdi | individual | other" string vn_mst "10 or 13 digits" bool vn_mst_validated string industry string country string address_street string address_ward string address_district string address_province string lead_source timestamp created_at uuid owner_member_id FK string custom_fields "json" } CONTACT { uuid id PK uuid tenant_id FK uuid account_id FK string first_name string last_name string display_name string email string phone_e164 string phone_raw string salutation "Anh | Chị | Bạn | Em" string title bool is_primary string custom_fields "json" } DEAL { uuid id PK uuid tenant_id FK uuid account_id FK uuid primary_contact_id FK string name string description_short int amount_minor_vnd int amount_minor_usd "nullable" string currency "VND | USD" string pipeline_id FK uuid stage_id FK int probability_pct date expected_close_date string status "open | won | lost | cancelled" string lost_reason "nullable" date closed_date uuid owner_member_id FK string acl_mode "default | restricted" timestamp created_at } PIPELINE { uuid id PK uuid tenant_id FK string name "sales | partner | inbound | outbound" bool default } STAGE { uuid id PK uuid pipeline_id FK string code string display_name_vi string display_name_en int order_idx int default_probability_pct string category "open | won | lost" } STAGE_TRANSITION { uuid id PK uuid deal_id FK uuid from_stage_id FK uuid to_stage_id FK uuid actor_id FK timestamp ts string brain_chain } ACTIVITY { uuid id PK uuid tenant_id FK uuid deal_id FK "nullable" uuid contact_id FK "nullable" uuid account_id FK "nullable" string kind "email | call | meeting | note | task | site_visit" string subject string body_markdown timestamp occurred_at string source "manual | email | chat | calendar | mcp" string source_event_id "idempotency key" uuid created_by FK } LEAD_SCORE { uuid deal_id PK int score_0_100 string tier "hot | warm | cold" string reasons "json array" timestamp computed_at } NBA_SUGGESTION { uuid deal_id PK string action_code "send_proposal | schedule_checkin | request_payment | …" string explanation_markdown int confidence_pct timestamp computed_at } VIETQR { uuid id PK uuid deal_id FK string bank_bin "970418 | …" string account_number int amount_minor_vnd string addinfo string qr_payload "EMVCo string" timestamp generated_at } HOA_DON { uuid id PK uuid deal_id FK string invoice_number string template_code int total_minor_vnd int vat_minor_vnd string xml_url "GDT-compliant XML" timestamp issued_at } CONTACT_MERGE_CANDIDATE { uuid id PK uuid contact_a FK uuid contact_b FK string match_reason "email | phone | both" float confidence string status "pending | merged | dismissed" } DEAL_ACL { uuid deal_id PK string allow_role_codes "csv" string allow_member_ids "csv" }

Vietnamese account types

CodeVietnameseEnglishMST lengthHóa đơn template
sole_proprietorHộ kinh doanhSole proprietor10 digits06GTKT (simplified)
llcCông ty TNHHLLC10 / 13 digits01GTKT
jscCông ty cổ phầnJSC10 / 13 digits01GTKT
fdiFDIForeign-invested10 / 13 digits01GTKT
individualCá nhânIndividual10 digits (CCCD-linked)06GTKT
otherKhácOthermanual
5

API surface

Four surfaces: a federated GraphQL subgraph (cross-module joins to PROJ Engagement and INV Invoice); a REST admin surface for bulk operations and migration import; a WebSocket sync for the pipeline drag-drop UI; and an MCP tool catalogue for CUO.

GraphQL subgraph

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

type Account @key(fields: "id") {
  id: ID!
  name: String!
  accountType: AccountType!
  vnMst: String
  vnMstValidated: Boolean!
  industry: String
  contacts: [Contact!]!
  deals(status: DealStatus): [Deal!]!
  activities(limit: Int = 50): [Activity!]!
  customFields: JSON
  leadSource: String
  owner: Subject
}

type Contact @key(fields: "id") {
  id: ID!
  account: Account!
  firstName: String!
  lastName: String!
  displayName: String!
  email: String
  phoneE164: String
  salutation: Salutation!
  title: String
  isPrimary: Boolean!
}

type Deal @key(fields: "id") {
  id: ID!
  account: Account!
  primaryContact: Contact
  name: String!
  amountMinorVnd: Int!
  currency: Currency!
  pipeline: Pipeline!
  stage: Stage!
  probabilityPct: Int!
  expectedCloseDate: Date
  status: DealStatus!
  leadScore: LeadScore
  nextBestAction: NBA
  activities: [Activity!]!
  vietqr: VietQR
  hoaDon: HoaDon
  acl: DealACL
}

enum AccountType { SOLE_PROPRIETOR LLC JSC FDI INDIVIDUAL OTHER }
enum Salutation { ANH CHI BAN EM NEUTRAL }
enum DealStatus { OPEN WON LOST CANCELLED }
enum Currency { VND USD }

type Mutation {
  createAccount(input: CreateAccountInput!): Account!
    @requiresScopes(scopes: [["crm.write"]])
  validateAccountMst(id: ID!): Account!
  createDeal(input: CreateDealInput!): Deal!
  moveDealStage(id: ID!, toStageId: ID!): Deal!
  generateVietQR(dealId: ID!, bankBin: String!, accountNumber: String!): VietQR!
  closeDeal(id: ID!, outcome: DealStatus!, lostReason: String): CloseDealResult!
    @requiresScopes(scopes: [["crm.close"]])
  logActivity(input: ActivityInput!): Activity!
  mergeContacts(keepId: ID!, mergeId: ID!): Contact!
    @requiresScopes(scopes: [["crm.contact.merge"]])
}

MCP tool catalogue

Tool nameInputsOutputsAnnotations
cyberos.crm.search_accountsquery, account_type?, limitAccount[]readonly
cyberos.crm.get_accountidAccountreadonly
cyberos.crm.create_accountCreateAccountInputAccountscope=crm.write
cyberos.crm.validate_mstmst{valid, name, address}readonly
cyberos.crm.list_dealsaccount_id?, pipeline_id?, stage_id?Deal[]readonly · scope=crm.read
cyberos.crm.create_dealCreateDealInputDealscope=crm.write
cyberos.crm.move_stagedeal_id, to_stageDealscope=crm.write
cyberos.crm.close_dealdeal_id, outcome, lost_reason?Deal + side-effectsdestructive · human-confirm · scope=crm.close
cyberos.crm.generate_vietqrdeal_id, bank_bin, account_numberVietQRscope=crm.payment
cyberos.crm.forecastpipeline_id?, rangeForecast with bandsreadonly
cyberos.crm.next_best_actiondeal_id?NBA[]readonly
6

Key flows

Flow 1 — Add an Account with MST validation

sequenceDiagram autonumber participant U as Member SPA participant API as CRM GraphQL participant MST as vn-mst-validate skill participant GDT as GDT registry participant PG as PostgreSQL participant B as BRAIN audit U->>API: createAccount {name, account_type:LLC, vn_mst:"0314…"} API->>API: validate MST format (10 or 13 digits) API->>MST: invoke skill {mst:"0314…"} MST->>GDT: HTTP GET registry endpoint GDT-->>MST: {name:"CÔNG TY TNHH ACME VN", address:"…"} MST-->>API: {valid:true, canonical_name, address} alt name match within tolerance API->>PG: INSERT account {vn_mst_validated:true} else mismatch API->>PG: INSERT account {vn_mst_validated:true, name=canonical_name} API-->>U: warning: name normalised to GDT value end API->>B: crm.account_created API-->>U: 200 Account

Flow 2 — Move deal through pipeline (drag-drop)

sequenceDiagram autonumber participant U as Member SPA participant WS as WebSocket participant API as CRM service participant PIPE as Pipeline rules participant PG as PostgreSQL participant N as NATS pipeline events participant B as BRAIN audit U->>U: optimistic move card to new stage U->>WS: deal.move_stage {deal_id, to_stage_id} WS->>API: dispatch API->>PIPE: validate transition (rule engine) alt allowed PIPE-->>API: ok API->>PG: INSERT stage_transition + UPDATE deal.stage_id API->>N: publish pipeline.{pipeline_id} N->>WS: fan-out to other SPAs API->>B: crm.stage_transition API-->>U: confirm (canonical state) else blocked PIPE-->>API: violation API-->>U: rollback + reason end

Flow 3 — Deal close → VietQR → hóa đơn → Engagement

sequenceDiagram autonumber participant U as Sales Member participant API as CRM participant VQR as vn-bank-transfer skill participant HD as vn-vat-invoice skill participant INV as 🧾 INV participant PROJ as 📋 PROJ participant BR as 🧠 BRAIN U->>API: closeDeal(id, outcome:WON) API->>API: validate user has crm.close scope API->>API: UPDATE deal.status=won, closed_date=today API->>VQR: generate VietQR (bank, account, amount, addinfo) VQR-->>API: {qr_payload, qr_image_url} API->>HD: emit hóa đơn (template based on account_type) HD->>HD: assemble XML per Circular 78/2021 HD-->>API: {invoice_number, xml_url} API->>INV: register invoice (status=issued) INV-->>API: invoice_id API->>PROJ: create Engagement (auto-link from Deal) PROJ-->>API: engagement_id API->>BR: crm.deal_closed {ingested into Layer 3 — closed deals only} API-->>U: 200 {deal, vietqr, invoice, engagement}

(FR pending): deals only ingested into BRAIN after closed / lost — open pipeline data never enters BRAIN.

Flow 4 — Email auto-log to CRM (tracked domain)

sequenceDiagram autonumber participant EM as ✉️ EMAIL inbound participant ACT as CRM activity feed participant PG as PostgreSQL participant N as NATS EM->>ACT: event {from:"buyer@acme.com", subject:"…", message_id} ACT->>PG: SELECT account WHERE domain = "acme.com" AND tracked=true alt account found ACT->>PG: SELECT contact WHERE email = "buyer@acme.com" ACT->>PG: INSERT activity {kind:"email", source_event_id=message_id} ON CONFLICT DO NOTHING ACT->>N: publish crm.activity.created else not tracked ACT-->>EM: ignore ((FR pending) boundary respected) end

Personal emails never auto-attach. Only tenant-configured tracked domains; the configuration is itself audited.

Flow 5 — AI lead scoring nightly batch

sequenceDiagram autonumber participant CR as Nightly cron participant SC as Lead scoring engine participant PG as PostgreSQL participant AG as ⚡ AI Gateway (CUO/CRO-skill) participant B as BRAIN audit CR->>SC: run for tenant SC->>PG: SELECT open deals + features (recency, value, account vertical, history) PG-->>SC: rows SC->>AG: chat.completions {features, scoring rubric} AG-->>SC: scores + reasons SC->>PG: UPSERT lead_score SC->>B: crm.lead_scoring_run {count, avg_score}
7

Deal lifecycle

A deal traverses the pipeline stages, ending in one of three terminal statuses (won, lost, cancelled). Stage transitions are governed by per-pipeline workflow rules.

stateDiagram-v2 [*] --> Qualifying: created Qualifying --> Discovery: budget + authority confirmed Discovery --> Proposal: needs scoped Proposal --> Negotiation: proposal sent Negotiation --> ClosedWon: contract signed Negotiation --> ClosedLost: lost reason recorded Negotiation --> Cancelled: client withdrew Discovery --> ClosedLost: dropped during discovery Proposal --> ClosedLost: rejected Qualifying --> Cancelled: unqualified ClosedWon --> [*] ClosedLost --> [*] Cancelled --> [*] Note right of ClosedWon: VietQR generated · hóa đơn issued · Engagement created in PROJ Note right of ClosedLost: lost_reason mandatory · win/loss analysis triggered

Default pipeline stages (sales)

CodevienDefault probabilityCategory
qualifyingĐánh giáQualifying10%open
discoveryKhám pháDiscovery25%open
proposalĐề xuấtProposal50%open
negotiationĐàm phánNegotiation75%open
closed_wonThắngClosed Won100%won
closed_lostThuaClosed Lost0%lost
cancelledHuỷCancelled0%lost
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

NFRs from PRD §11.2 that CRM must satisfy.

NFR IDConcernTargetMeasurement
N(FR pending)Pipeline view load (200 deals)p95 ≤ 350 msSPA RUM
N(FR pending)Stage drag-drop responsep95 ≤ 200 msWS latency histogram
N(FR pending)Account search (10k accounts)p95 ≤ 300 msk6
N(FR pending)MST validationp95 ≤ 1.5 s (cache-cold)histogram
N(FR pending)Pipeline drag-drop drop-rate (loss)= 0BRAIN audit reconciliation
N(FR pending)Vietnamese salutation accuracy≥ 92% on 200-contact evalquarterly review
N(FR pending)Service availability≥ 99.9% (28-day)OBS SLO
N(FR pending)Private-deal isolation= 0 cross-leakCI test + quarterly red-team
N(FR pending)Personal email auto-attach= 0 (tracked-domain only)policy gate test
N(FR pending)Activity-feed idempotency= 0 duplicatesidempotency key DB constraint
N(FR pending)Deal close → Engagement durability100% within 60 sBRAIN audit cross-check
N(FR pending)Hóa đơn XML schema compliance100% pass Circular 78/2021CI test against GDT XSD
10

Dependencies

CRM depends on AUTH (every call), BRAIN (activity ingest + audit), EMAIL (auto-log), CHAT (meeting notes), Calendar (attendance), AI (scoring + NBA + forecast), MCP, OBS, and three CyberOS skills (vn-mst-validate, vn-bank-transfer, vn-vat-invoice). It is depended on by PROJ (Engagement creation), INV (hóa đơn emission), and PORTAL (client-visible deal status at P2+).

graph LR subgraph upstream ["CRM depends on"] AUTH["🔐 AUTH"] BRAIN["🧠 BRAIN"] EMAIL["✉️ EMAIL"] CHAT["💬 CHAT"] CAL["📅 Calendar"] AI["⚡ AI Gateway"] MCP["🔌 MCP"] OBS["👁 OBS"] MST["vn-mst-validate"] VQR["vn-bank-transfer"] HD["vn-vat-invoice"] end CRM["🤝 CRM"] subgraph downstream ["CRM is depended on by"] PROJ["📋 PROJ"] INV["🧾 INV"] PORTAL["Portal · P2"] end AUTH --> CRM BRAIN --> CRM EMAIL --> CRM CHAT --> CRM CAL --> CRM AI --> CRM MCP --> CRM OBS --> CRM MST --> CRM VQR --> CRM HD --> CRM CRM --> PROJ CRM --> INV CRM --> PORTAL classDef shipped fill:#f5ede6,stroke:#45210e classDef planned fill:#fef6e0,stroke:#9c750a class BRAIN,MST,VQR,HD shipped class CRM,AUTH,EMAIL,CHAT,CAL,AI,MCP,OBS,PROJ,INV,PORTAL planned
11

Compliance scope

CRM holds Customer personal data and processes hóa đơn-relevant fields; it sits inside PDPL / Circular 78/2021 / GDPR scope.

Regulation / standardArticle / clauseCRM feature that satisfies it
Vietnam PDPL (Law 91/2025)Art. 14 — DSARDSAR export includes contact + activity + deal data.
Vietnam Decree 13/2023Art. 17 — Processing logEvery CRM mutation writes a BRAIN audit row.
Vietnam Decree 53/2022Art. 26 — ResidencyPer-tenant residency tag; VN tenants on hanoi-1.
Vietnam Circular 78/2021/TT-BTCHóa đơn e-invoice formatvn-vat-invoice emits compliant XML.
Vietnam Decree 123/2020/NĐ-CPInvoice issuance & storageHOA_DON table with XML link + 10-year retention.
GDPR (EU 2016/679)Art. 17 — Right to erasureContact delete + DSAR-driven hard purge.
GDPRArt. 25 — Privacy by designPer-deal ACL prevents cross-workspace leak.
ISO/IEC 27001:2022A.8.2 — Privileged accessRBAC + per-deal ACL.
SOC 2 Type IICC6.1 — Logical accessRLS + ACL enforced at every mutation.
OWASP Top-10 (web)A01 — Broken access controlACL enforced server-side; CI test on every PR.
12

Risk entries

CRM-specific risks tracked in the risk register.

IDRiskLikelihoodImpactOwnerMitigation
R-CRM-001GDT MST registry endpoint outageMediumMediumCTO7-day cache; validation marked stale; user warned but write permitted.
R-CRM-002Hóa đơn XML schema drift breaks emissionMediumHighCFOCI test against GDT XSD weekly; skill version pinned; rollback plan documented.
R-CRM-003Personal email auto-attaches to CRM via misconfigLowHighCSOTracked-domain config audited; CI test asserts personal domains stay out.
R-CRM-004Private-deal leak via cross-workspace GraphQL queryLowHighCSOACL CI gate; quarterly red-team on subgraph.
R-CRM-005Activity-feed duplicate from EMAIL retryMediumLowCTOIdempotency key on source event id; DB unique constraint.
R-CRM-006Lead-scoring bias against specific account verticalsMediumMediumCDOQuarterly fairness review of scoring inputs; reasons surfaced to user.
R-CRM-007VietQR generated with wrong account number → payment misdirectedLowHighCFOPer-tenant bank-account allow-list; Member confirm step on first use.
R-CRM-008Merge proposes false-positive (same email shared family)MediumLowCROMerge requires explicit Member confirm; confidence threshold ≥ 0.85.
R-CRM-009BRAIN ingest of closed deals leaks competitive dataLowMediumCDOClosed deals respect deal ACL on BRAIN side; private deals never ingested.
R-CRM-010Open-pipeline data ingested into BRAIN by accident ((FR pending) violation)LowHighCDOBRAIN ingest path gated by deal.status & ('won','lost'); CI test asserts.
13

KPIs

CRM rolls up 10 KPIs covering pipeline health, AI feature efficacy, integration durability, and VN-specific flow correctness.

KPIFormulaSourceTarget
Pipeline value (VND)sum(open_deal.amount × probability)PGtracked daily
Stage drag-drop p95histogramOBS≤ 200 ms
Win ratewon / (won + lost)BRAIN audittracked per pipeline
Average deal cyclemedian(closed_date − created_at)BRAIN audittracked per Engagement type
Lead-scoring precisiontrue_hot / scored_hotretrospective on wins≥ 70%
NBA acceptanceactioned / suggestedSPA telemetrytracked; target ≥ 35%
Activity auto-log durabilitylogged / source_eventsEMAIL ↔ CRM reconciliation100%
Hóa đơn emission successissued / close_wonBRAIN audit100%
MST validation ratevalidated / vn_accountsBRAIN audit≥ 95%
Cross-workspace ACL violationscountBRAIN audit= 0
14

RACI matrix

CRM is owned by CRO seat (interim CEO).

ActivityCEOCROCFOCTOCSOCMO
Service design + specARCCCC
ImplementationICIA/RCI
Pipeline / stage configCA/RIIIC
Tracked-domain configIAIRCI
Hóa đơn flow reviewICA/RCII
Lead-scoring fairness reviewCAICIR
ACL auditCCIRAI
DSAR fulfilmentICCCRI
Incident responseARCRRI

R Responsible · A Accountable · C Consulted · I Informed.

15

Planned CLI surface

cyberos-crm for tenant operators and bulk import / export.

1. Add a Vietnamese LLC account

$ cyberos-crm account create \
    --name "ACME Vietnam Co., Ltd." \
    --type llc \
    --mst 0314556677 \
    --owner stephen@cyberskill.world

[mst]      vn-mst-validate skill invoked
[mst]      ✓ matches GDT registry: "CÔNG TY TNHH ACME VIỆT NAM"
[mst]      ⚠ name normalised to GDT canonical
[create]   account_id: 01HZK7…
[audit]    brain seq=15301 chain=…

2. List contacts at an account

$ cyberos-crm contact list --account 01HZK7…

display_name              email                  phone          salutation  primary
Nguyễn Văn A              vana@acme.vn           +84903123456   Anh          yes
Trần Thị B                thib@acme.vn           +84909222333   Chị          no
Phạm Minh C               minhc@acme.vn          +84908111222   Anh          no

3. Move a deal stage

$ cyberos-crm deal move --id 01HZK8… --to-stage proposal

[validate]   transition discovery → proposal allowed
[move]       deal status: open  stage: proposal  probability: 50%
[ws]         broadcast to 4 connected SPAs
[audit]      brain seq=15315 chain=…

4. Close a deal (won) — full flow

$ cyberos-crm deal close --id 01HZK8… --outcome won

[close]      status=won · closed_date=2026-05-14
[vietqr]     vn-bank-transfer skill invoked
[vietqr]     generated: bank=Vietcombank · account=0011 0023 4567 · amount=750,000,000 VND
[hoadon]     vn-vat-invoice skill invoked (template=01GTKT)
[hoadon]     invoice_number: C26TAA/0001234 · XML: s3://cyberos/hoadon/01HZK9…xml
[inv]        INV invoice registered (id=01HZKB…)
[proj]       Engagement created: "ACME Q3 platform build"
[brain]      deal ingested into Layer 3 (closed deal)
[audit]      brain seq=15327 chain=…

5. Forecast

$ cyberos-crm forecast --pipeline sales --range 90d

pipeline:  sales (next 90 days)
band       vnd_low         vnd_mid         vnd_high
50%        1,200,000,000   1,450,000,000   1,750,000,000
80%          800,000,000   1,100,000,000   1,500,000,000
95%          500,000,000     750,000,000   1,100,000,000

top 5 deals by probability×value:
  01HZK8… ACME Q3 build      750,000,000   75%
  01HZKC… BetaCo retainer    240,000,000   80%
  …

6. Merge contacts

$ cyberos-crm contact merge --keep 01HZKD… --merge 01HZKE…

[merge]   keep: Nguyễn Văn A (vana@acme.vn)
[merge]   merge: A Nguyen Van (vana@acme.vn)  ← duplicate
[merge]   ✓ activities reassigned: 47
[merge]   ✓ deals reassigned: 3
[merge]   ✓ contact 01HZKE… tombstoned
[audit]   brain seq=15334 chain=…

7. DSAR export for a contact

$ cyberos-crm dsar-export --contact 01HZKD… --output a-nguyen.zip

[dsar]   contact:    01HZKD… Nguyễn Văn A
[dsar]   activities: 412
[dsar]   deals:      6 (3 won, 1 lost, 2 cancelled)
[dsar]   written:    a-nguyen.zip (8 MB)
16

Phase status & estimates

Status
Planned
P1 · design phase
Est. LoC
~8,500
Rust + TS pipeline UI
Planned tests
100+
incl. ACL fuzzing
External libs
~12
axum · sqlx · libphonenumber
CLI subcommands
~20 planned
cyberos-crm
P1 budget
~$60/mo
Fargate + RDS + Redis
CapabilityStatus
Account / Contact / Deal CRUDplanned · P1
Configurable pipeline + stagesplanned · P1
WebSocket drag-drop pipelineplanned · P1
Activity auto-log (EMAIL / CHAT / Calendar)planned · P1
vn-mst-validate integrationplanned · P1
vn-bank-transfer (VietQR)planned · P1
vn-vat-invoice (hóa đơn)planned · P1
Deal close → PROJ Engagementplanned · P1
AI lead scoring (nightly batch)planned · P1
Next-best-action suggestionplanned · P1
Confidence-banded forecastplanned · P1
Contact merge candidate detectionplanned · P1
Per-deal ACLplanned · P1
Vietnamese salutation helperplanned · P1
HubSpot / Salesforce migration importplanned · P2+
Client-visible PORTAL viewplanned · P2+
17

References

  • PRD §9.11 — CRM product FRs.
  • PRD §19.6 — CRM SRS-tier FRs.
  • PRD §11.2 — NFRs.
  • SRS §4.11 — Formal (FR pending) through (FR pending).
  • Vietnam Decree 123/2020/NĐ-CP — Electronic invoice issuance and storage.
  • Vietnam Circular 78/2021/TT-BTC — Hóa đơn format.
  • Vietnam PDPL (Law 91/2025/QH15).
  • Vietnam Decree 13/2023 — Personal data.
  • Napas247 / VietQR specification — bank transfer QR.
  • vn-mst-validate skill — CyberOS skill for MST validation.
  • vn-bank-transfer skill — VietQR generator.
  • vn-vat-invoice skill — hóa đơn generator.
  • libphonenumber — E.164 normalisation.
  • Architecture context: infrastructure.html#crm.