On this page
1. The PR contains more than "CRM"2. Stray artifacts committed at the repo root3. One CRM claim is asserted without evidence in the repo4. Web vs mobile: known asymmetries5. Deliberately deferred (fromdocs/crm-runbooks.md)6. Stubbed in the UI on purpose7. Deploy prerequisites (from docs/crm-integration-setup.md + crm-runbooks.md)Scope, Gaps & Honest Notes
This page exists because good documentation describes what the code actually does — and, where the PR's claims and the code diverge, says so plainly. Nothing here is a criticism of the work; it's the map a reviewer, tester, or release manager needs.
1. The PR contains more than "CRM"
What the PR says: the title and description of PR #159 are entirely about the CRM module (integrations, inbox, marketing hub, automation, reviews).
What the diff actually contains: also a large, fully-wired accounting module that the PR description never mentions — roughly 10,000 lines of server code (packages/server/src/accounting/*, ~74 files including a test suite) plus ~54 mobile accounting screens and ~106 mobile accounting GraphQL operation files. It is not dead code: accounting.graphql is picked up by the schema glob (server.js:25), posting handlers are threaded into invoices/expenses/payments/salary flows, and it has its own feature flag FEATURE_ACCOUNTING_MODULE seeded in the same file as the CRM flags (seedFeatureFlags.js:97).
How they relate: the two modules genuinely interlock at one seam — the CRM's Ad-spend Accounting bridge posts ad spend to the accounting general ledger (accounting/posting/adSpend.js), and the Marketing Hub's "Booked Spend / Posted to GL" figures come from there. But the accounting module is far larger than that seam.
Honest characterization: treat this PR as two logically separate deliverables shipped under one CRM-titled PR. This walkthrough documents the CRM module (the named feature and the sandbox's focus). The accounting module warrants its own walkthrough and is only referenced here where the CRM touches it. Git history was not available in this environment, so the exact base-vs-branch provenance of the accounting code could not be confirmed — whoever has git access should verify it.
2. Stray artifacts committed at the repo root
Two files look like accidental scratch commits and don't belong in the PR:
account-mapping-initial.png— a screenshot of the accounting Account Mapping screen.acct-map-revenue.md— despite the name, this is not a design doc; it's a raw
Playwright accessibility-tree dump captured from the accounting Account-Mapping screen. Mislabeled and accounting-related, not CRM.
(README.md at the repo root is also effectively empty — 1 byte — and docs/release-001-code-review-issues.md is an unrelated older code-review document. Worth a glance before merge.)
3. One CRM claim is asserted without evidence in the repo
The PR body and docs/crm-runbooks.md state the webhook path was burst-tested at ~1,266 req/s, p99 56ms, zero drops, with verified self-heal after a simulated outage. The inbox design plausibly supports high throughput (fast ack, async processing, idempotent replay), but there is no load-test harness, benchmark script, or result artifact in the repo (no autocannon/k6/artillery). Treat the throughput figure as an unverified claim, not a documented, reproducible result. Every other spot-checked claim (AES-256-GCM vault, durable WebhookEvent inbox, Arabic-Indic phone dedupe, 90-day PII redaction, feature flags + seed-feature-flags, tracked /r/<code> links) is code-verified.
4. Web vs mobile: known asymmetries
| Area | Web | Mobile |
|---|---|---|
| Feature-flag gating of CRM | All CRM behind FEATURE_CRM_* | None — gated only on permissions + company.leadsEnabled |
| OAuth "Connect" | Yes (Meta SDK popup + redirect OAuth) | No — view/refresh/disconnect/map only |
| CRM Setup Checklist | Yes (web-only onboarding card) | No |
| Inbox conversation panel / live countdown | Yes | Static window banner instead |
| Automation action reorder | Yes | No |
The most consequential row is the first: a clinic with leadsEnabled can see CRM screens on mobile even if the web feature flags are off. Worth confirming this is intended before GA.
5. Deliberately deferred (from docs/crm-runbooks.md)
- TikTok / Snapchat / Google adapters — implemented and mock-verified against
packages/platform-mock, but each still needs a one-time real-credential smoke test before its flag is turned on. In the sandbox these platforms' Connect buttons are disabled.
- Google Ads spend sync + Google Business Profile reviews/NPS — blocked on Google API
approvals. The setup guide flags GBP as the slowest approval (default quota 0, 2–6+ weeks) — submit it first even though reviews ship after Ads.
- Physical drop of deprecated
Leadcolumns — a follow-up PR after a soak period, with
data-preservation SQL. Until then the columns remain and a CI tripwire (scripts/audit-deprecated-lead-fields.sh) prevents new code from using them.
AdInsight13-month rollup/retention job — deferred until data volume warrants it
(~1M rows).
6. Stubbed in the UI on purpose
Five automation triggers exist in the schema — TAG_ADDED, APPOINTMENT_NO_SHOW, CONVERSATION_UNANSWERED, LEAD_WON, LEAD_REJECTED — but no code emits them yet, so both the web and mobile builders hide them and show a "coming soon" hint (automationHelpers.js:4). Only LEAD_CREATED, STAGE_CHANGED, and STALE_IN_STAGE are live.
7. Deploy prerequisites (from docs/crm-integration-setup.md + crm-runbooks.md)
SOCIAL_TOKEN_ENC_KEY(base64 32-byte AES key; gateway fails fast at boot without it);
SOCIAL_TOKEN_ENC_KEY_ID + SOCIAL_TOKEN_ENC_KEYS_OLD for rotation.
WEBHOOKS_PUBLIC_URL(builds webhook URLs, OAuth redirects, and/r/<code>links).CRM_*cron variables;META_GRAPH_URLunset in production (set only in QA to point at
platform-mock).
- One-off
yarn encrypt-wa-tokensto re-encrypt the legacy WhatsApp token. - Per-platform: business verification + a bundled Advanced Access review before GA; app
credentials set on server and gateway.