@cometchat/skills 5.0.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +8 -0
- package/MIGRATING.md +187 -0
- package/README.md +19 -1
- package/RULES.md +12 -1
- package/bin/cometchat-skills.mjs +106 -6
- package/package.json +8 -3
- package/peers.yaml +46 -3
- package/registry/android-calls-v5.json +40 -0
- package/registry/android-v6.json +40 -0
- package/registry/angular-v5.json +40 -0
- package/registry/flutter-calls-v5.json +40 -0
- package/registry/flutter-v6.json +40 -0
- package/registry/ios-calls-v5.json +40 -0
- package/registry/ios-v5.json +55 -0
- package/registry/rn-calls-v5.json +40 -0
- package/registry/rn-v5.json +40 -0
- package/registry/sdk-android-v5.json +40 -0
- package/registry/sdk-jsv4.json +40 -0
- package/registry/web-calls-v5.json +40 -0
- package/registry/web-v7.json +55 -0
- package/skills/cometchat/SKILL.md +8 -3
- package/skills/cometchat-a11y/SKILL.md +49 -0
- package/skills/cometchat-analytics/SKILL.md +61 -0
- package/skills/cometchat-android-v6-core/references/docs-map.md +2 -2
- package/skills/cometchat-android-v6-production/SKILL.md +1 -0
- package/skills/cometchat-angular-v5-production/SKILL.md +1 -0
- package/skills/cometchat-audit/SKILL.md +61 -0
- package/skills/cometchat-compliance/SKILL.md +63 -0
- package/skills/cometchat-flutter-v6-customization/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-migration/references/migration-guide.md +8 -7
- package/skills/cometchat-flutter-v6-production/SKILL.md +1 -0
- package/skills/cometchat-i18n/SKILL.md +50 -0
- package/skills/cometchat-ios-core/SKILL.md +3 -2
- package/skills/cometchat-ios-core/references/anti-patterns.md +33 -0
- package/skills/cometchat-ios-core/references/docs-map.md +4 -3
- package/skills/cometchat-ios-core/references/layout.md +33 -0
- package/skills/cometchat-ios-production/SKILL.md +82 -0
- package/skills/cometchat-ios-testing/SKILL.md +57 -0
- package/skills/cometchat-ios-troubleshooting/SKILL.md +45 -0
- package/skills/cometchat-migrate-from-getstream/SKILL.md +65 -0
- package/skills/cometchat-migrate-from-getstream/references/concept-map.md +98 -0
- package/skills/cometchat-migrate-from-getstream/references/data-migration.md +74 -0
- package/skills/cometchat-migrate-from-getstream/references/feature-map.md +108 -0
- package/skills/cometchat-migrate-from-getstream/references/inventory.md +82 -0
- package/skills/cometchat-migrate-from-getstream/references/native-build.md +9 -0
- package/skills/cometchat-migrate-from-getstream/references/report-template.md +59 -0
- package/skills/cometchat-migrate-from-sendbird/SKILL.md +64 -0
- package/skills/cometchat-migrate-from-sendbird/references/concept-map.md +99 -0
- package/skills/cometchat-migrate-from-sendbird/references/data-migration.md +74 -0
- package/skills/cometchat-migrate-from-sendbird/references/feature-map.md +104 -0
- package/skills/cometchat-migrate-from-sendbird/references/inventory.md +86 -0
- package/skills/cometchat-migrate-from-sendbird/references/native-build.md +10 -0
- package/skills/cometchat-migrate-from-sendbird/references/report-template.md +59 -0
- package/skills/cometchat-migrate-from-twilio/SKILL.md +52 -0
- package/skills/cometchat-migrate-from-twilio/references/concept-map.md +49 -0
- package/skills/cometchat-migrate-from-twilio/references/data-migration.md +50 -0
- package/skills/cometchat-migrate-from-twilio/references/feature-map.md +27 -0
- package/skills/cometchat-migrate-from-twilio/references/inventory.md +53 -0
- package/skills/cometchat-migrate-from-twilio/references/report-template.md +52 -0
- package/skills/cometchat-moderation/SKILL.md +58 -0
- package/skills/cometchat-onboarding/SKILL.md +4 -1
- package/skills/cometchat-onboarding/references/platforms.md +15 -0
- package/skills/cometchat-react-native-core/SKILL.md +25 -3
- package/skills/cometchat-react-native-core/references/docs-map.md +2 -1
- package/skills/cometchat-react-native-production/SKILL.md +1 -0
- package/skills/cometchat-react-native-sdk/SKILL.md +16 -9
- package/skills/cometchat-react-native-troubleshooting/SKILL.md +58 -0
- package/skills/cometchat-react-v7-core/SKILL.md +4 -4
- package/skills/cometchat-react-v7-core/references/anti-patterns.md +1 -1
- package/skills/cometchat-react-v7-core/references/component-props.md +1 -1
- package/skills/cometchat-react-v7-core/references/layout.md +4 -12
- package/skills/cometchat-react-v7-production/SKILL.md +84 -0
- package/skills/cometchat-react-v7-testing/SKILL.md +60 -0
- package/skills/cometchat-react-v7-troubleshooting/SKILL.md +47 -0
- package/skills/cometchat-security/SKILL.md +80 -0
- package/skills/cometchat-self-host/SKILL.md +56 -0
- package/test-suite/catalogs/flutter-calls-v5.json +1 -1
- package/test-suite/scripts/lint-skills.mjs +30 -7
- package/test-suite/scripts/verify-family-agnostic.mjs +5 -1
- package/skills/cometchat-react-v7-core/references/i18n-rtl-a11y.md +0 -22
- package/skills/cometchat-react-v7-core/references/troubleshooting.md +0 -28
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cometchat-react-v7-testing
|
|
3
|
+
description: "Test a React app that embeds CometChat v7 — what to mock vs exercise for real, rendering kit components under a test provider, waiting out the async init→login gate, and a lean E2E smoke. Triggers: 'test my cometchat react app', 'mock cometchat in jest/vitest', 'unit test chat component', 'playwright test for chat', 'how do I test cometchat'."
|
|
4
|
+
license: "MIT"
|
|
5
|
+
compatibility: "@cometchat/chat-uikit-react ^7 (7.1.x–7.2.x verified); React 18–19; Vitest / Jest / React Testing Library / Playwright"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "CometChat"
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
tags: "cometchat react v7 testing vitest jest playwright mock rtl"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
> **Ground truth:** `@cometchat/chat-uikit-react@7`. Component/method names come from `cometchat-react-v7-core` + its catalog; signatures are FETCHED via `cometchat-react-v7-core/references/docs-map.md`. **The UI Kit docs have no dedicated testing page** — this is the pack's own guidance (tracked DOCS GAP). Never assert against kit-internal DOM classes; they are not a public contract.
|
|
13
|
+
|
|
14
|
+
## Companion skills (read first)
|
|
15
|
+
- `cometchat-react-v7-core` — the init→login→render lifecycle these tests exercise.
|
|
16
|
+
|
|
17
|
+
## Use this skill when
|
|
18
|
+
Adding tests around a CometChat integration, or a "how do I test this" question. NOT part of a normal build — only when tests are explicitly asked for (`RULES.md` → Verification scope).
|
|
19
|
+
|
|
20
|
+
## Decide what you are testing
|
|
21
|
+
You are testing **your** code, not CometChat's kit. Three layers:
|
|
22
|
+
- **Your logic** (token fetch, UID mapping, routing, state) → unit-test in isolation, **mock the SDK**.
|
|
23
|
+
- **Your wiring** (does the surface mount after init+login, are the right props passed) → render under a test provider with the SDK mocked.
|
|
24
|
+
- **The real round-trip** (send → receive) → a thin E2E against a test app, not a unit test.
|
|
25
|
+
|
|
26
|
+
Do not unit-test that `CometChatMessageList` renders messages — that is the kit's own test surface.
|
|
27
|
+
|
|
28
|
+
## Mock the SDK in unit tests
|
|
29
|
+
Mock the two entry modules so nothing hits the network and no real login is attempted:
|
|
30
|
+
```tsx
|
|
31
|
+
vi.mock("@cometchat/chat-sdk-javascript", () => ({ CometChat: { getLoggedinUser: vi.fn().mockResolvedValue(null) } }));
|
|
32
|
+
vi.mock("@cometchat/chat-uikit-react", async (orig) => ({
|
|
33
|
+
...(await orig()),
|
|
34
|
+
CometChatUIKit: { initFromSettings: vi.fn().mockResolvedValue(null), getLoggedInUser: vi.fn().mockReturnValue(null), login: vi.fn().mockResolvedValue({ getUid: () => "u1" }), loginWithAuthToken: vi.fn().mockResolvedValue({ getUid: () => "u1" }), logout: vi.fn().mockResolvedValue(undefined) },
|
|
35
|
+
}));
|
|
36
|
+
```
|
|
37
|
+
(Jest: swap `vi` for `jest`.) Now assert your own token-fetch and error handling without a backend.
|
|
38
|
+
|
|
39
|
+
## Render the surface under test
|
|
40
|
+
The kit surface mounts only **after** init+login resolve. Tests must await that gate, not assert synchronously:
|
|
41
|
+
```tsx
|
|
42
|
+
render(<App />);
|
|
43
|
+
expect(await screen.findByText(/sign in|loading|chats/i)).toBeInTheDocument();
|
|
44
|
+
```
|
|
45
|
+
Prefer `findBy*` (async) over `getBy*`; a synchronous query runs before the init promise settles and fails intermittently. Wrap the surface in `CometChatErrorBoundary` in the app so a thrown error surfaces as a testable fallback, not an unhandled rejection.
|
|
46
|
+
|
|
47
|
+
## E2E smoke (Playwright)
|
|
48
|
+
One high-value path against a **real test app** (seeded users, dev Auth Key in a test-only env): load the app, sign in, assert the conversation list renders with real height and a message can be sent. Assert on **your** visible text/roles and the presence of the mounted surface — not on kit BEM classes. Keep it to the happy path plus one auth-failure path; the kit's internals are already tested upstream.
|
|
49
|
+
|
|
50
|
+
## Not worth automating
|
|
51
|
+
Kit component internals, exhaustive prop matrices, live calls/push (device-dependent), and pixel snapshots of kit UI (they churn across minor kit versions). Spend the budget on your token flow, UID mapping, and the init-gate wiring.
|
|
52
|
+
|
|
53
|
+
## Common pitfalls
|
|
54
|
+
1. **Synchronous assertions before init resolves** — flaky; use `findBy*`/`waitFor`.
|
|
55
|
+
2. **Asserting on kit DOM classes** — they change across versions; assert your own markup + roles.
|
|
56
|
+
3. **A real login in unit tests** — mock `CometChatUIKit`; never ship a test Auth Key to prod env files.
|
|
57
|
+
4. **StrictMode double-invoke** — mocks must be idempotent (return the same resolved user), mirroring the app's in-flight guard.
|
|
58
|
+
|
|
59
|
+
## Verify it works
|
|
60
|
+
Unit tests pass with the SDK mocked (no network) · the surface test awaits the init gate and finds the mounted UI · the E2E smoke signs in and renders conversations against a test app · no test asserts a kit-internal class.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cometchat-react-v7-troubleshooting
|
|
3
|
+
description: "Diagnose a broken CometChat React v7 integration — blank panes, a collapsed/0-height surface, empty lists, no messages, the kit's error state, events that never fire, or a version_conflict. Triggers: 'cometchat react not working', 'chat is blank', 'conversations empty', 'messages not showing react', 'something went wrong cometchat', 'cometchat react errors', 'why is my chat broken'."
|
|
4
|
+
license: "MIT"
|
|
5
|
+
compatibility: "@cometchat/chat-uikit-react ^7 (7.1.x–7.2.x verified); React 18–19; Vite / Next.js / CRA / React Router / Astro"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "CometChat"
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
tags: "cometchat react v7 troubleshooting debug diagnostics blank-screen version-conflict"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
> **Ground truth:** `@cometchat/chat-uikit-react@7`. Symbols/signatures are verified against `cometchat-react-v7-core` + its catalog and FETCHED via `references/docs-map.md`; the rules referenced (init order, layout sizing, credentials) are `RULES.md`. This diagnostics catalog is cross-checked against the live `{DOCS_BASE}/ui-kit/react/troubleshooting.md` page (base + paths in `cometchat-react-v7-core/references/docs-map.md`), and adds the host-side/runtime symptoms it doesn't cover.
|
|
13
|
+
|
|
14
|
+
## Companion skills (read first)
|
|
15
|
+
- `cometchat-react-v7-core` — the correct init→login→render order, credentials, and the reflow-free layout the fixes below restore.
|
|
16
|
+
|
|
17
|
+
## Use this skill when
|
|
18
|
+
A React CometChat integration compiles but misbehaves at runtime: blank, empty, unresponsive, or throwing.
|
|
19
|
+
|
|
20
|
+
## Start here — React fails on the ORDER and the BOX
|
|
21
|
+
Two causes explain most "it's blank":
|
|
22
|
+
1. **A kit component rendered before `init()` + `login()` resolved.** The surface must be gated on the resolved logged-in user. Rendering it eagerly (or during SSR) yields an empty/erroring pane.
|
|
23
|
+
2. **The container has no height.** The kit fills its parent; a parent at `height:auto`/`0` collapses it to a sliver. This is a host CSS defect, not a kit bug (`RULES.md` → Layout / sizing).
|
|
24
|
+
|
|
25
|
+
## Symptom → cause → fix
|
|
26
|
+
| Symptom | Likely cause | Fix |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| Blank/white, no errors | Surface rendered before init+login resolved | Gate render on the resolved user; keep `CometChatErrorBoundary` for a visible fallback |
|
|
29
|
+
| Blank during SSR / `window is not defined` | A kit component imported or rendered on the server (Next.js, Astro, Remix) | Render the surface client-only — `"use client"` + `dynamic(..., { ssr:false })` (Next), `client:only` (Astro); see core `references/ssr.md` |
|
|
30
|
+
| Surface ~0px / cramped top-left | Ancestor chain has no height | `html,body,#root{height:100%}` + a pinned surface (`100dvh` full-app) + panes `min-height:0`; see core `references/layout.md` |
|
|
31
|
+
| "OOPS! Looks like something went wrong" | The kit's error state — a call threw (often a custom `ConversationsRequestBuilder` with no `.setLimit(n)`, or a bad Region) | Add `.setLimit(30)`; confirm Region matches the dashboard app |
|
|
32
|
+
| Conversations empty | New/seeded app has no conversations yet, or scope excludes them | Send a first message; check `conversationsRequestBuilder` scope (`user`/`group`) matches intent |
|
|
33
|
+
| `login()` fails "user not found" | UID does not exist in the app | Use a real UID (Dashboard → Users; fresh apps seed `cometchat-uid-1`) — never a guessed `superhero*` |
|
|
34
|
+
| Nothing updates live | Missing/duplicated listeners, or StrictMode double-mount | Add listeners with a stable ID, remove on unmount; guard the init/login in-flight (`cometchat-react-v7-patterns`) |
|
|
35
|
+
| Roster rows appear TWICE + ~30 "duplicate key" errors (dev only) | React **StrictMode** double-invokes effects; the roster drop-ins `CometChatUsers`/`CometChatGroups`/`CometChatGroupMembers` double-append (kit de-dupe gap; `CometChatConversations` is unaffected) | A dev-only StrictMode artifact — gone in `vite build`/prod. Do **NOT** remove StrictMode to "fix" it; verify the roster in a production build. Kit issue — report upstream |
|
|
36
|
+
| Localized keys shown raw (e.g. `group_info`) | Wrong/stale i18n key or provider missing | Use the kit component / correct key; ensure `CometChatProvider` wraps the tree |
|
|
37
|
+
| Works in dev, blank in prod | Wrong env prefix → Auth Key/App ID missing in the bundle | Fix the bundler prefix; grep the build (`cometchat-react-v7-production`) |
|
|
38
|
+
| `version_conflict` on detect | Project on UI Kit v6 while skills target v7 | STOP and reconcile — migrate v6→v7 (`cometchat-react-v7-migration`), or stay on v6 by installing the older **v4 skills pack** (it targets the v6 UI Kit) |
|
|
39
|
+
|
|
40
|
+
## When the table does not cover it
|
|
41
|
+
Open the browser console + network tab: a `401` is auth (bad token/Auth Key/Region), a `402` is a plan-gated feature (e.g. Search — enable it in the dashboard), a `4xx` "no conversation yet" is benign. Then fetch the feature's page via `cometchat-react-v7-core/references/docs-map.md`. Never diagnose from `node_modules`/`.d.ts` or memory.
|
|
42
|
+
|
|
43
|
+
## Verify it works
|
|
44
|
+
Init+login resolve before the surface renders · the surface has real dimensions (not a sliver) · conversations render or show the kit's empty state (not the error state) · a message sends and arrives live · no raw localization keys · production build carries no Auth Key.
|
|
45
|
+
|
|
46
|
+
## What NOT to do
|
|
47
|
+
Do not silence the error boundary to hide a thrown call; do not hard-code a UID to dodge "user not found"; do not read kit internals to work around a missing prop — fetch the documented prop instead.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cometchat-security
|
|
3
|
+
description: "Enterprise auth & access control for CometChat — SSO/OIDC/SAML via your own IdP, server-minted auth tokens, token revocation & session control, and role-based access (RBAC app-wide roles + group scopes). Cross-family: the server/REST side is the same everywhere; client login lands in each family's core/production skill. Triggers: 'add SSO to cometchat', 'SAML/OIDC login', 'okta/auth0/cognito with cometchat', 'role based access control', 'restrict what a user can do', 'revoke a user session', 'rotate/flush auth tokens', 'secure cometchat for enterprise', 'multi-tenant cometchat'."
|
|
4
|
+
license: "MIT"
|
|
5
|
+
compatibility: "CometChat REST API v3 (auth tokens · roles · users · group members). Client login via any family's UI Kit / SDK. Server: any language over HTTPS."
|
|
6
|
+
metadata:
|
|
7
|
+
author: "CometChat"
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
tags: "cometchat security sso saml oidc rbac roles auth-token session enterprise multi-tenant"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
> **Ground truth:** every REST shape here is FETCHED from the live docs — `{DOCS_BASE}/rest-api/auth-tokens`, `/rest-api/roles`, `/rest-api/rbac-overview`, `/rest-api/users`, `/rest-api/group-members` (`DOCS_BASE = https://www.cometchat.com/docs`; append `.md` for the raw twin). **CometChat is NOT an identity provider** — it does not do SAML/OIDC for your end users. "SSO with CometChat" means *your* IdP authenticates the user, then *your server* mints a CometChat auth token for that user's UID. Verify signatures against the docs; never invent an endpoint.
|
|
13
|
+
|
|
14
|
+
## Use this skill when
|
|
15
|
+
Taking a CometChat integration through an enterprise security review: SSO with your IdP, role-based permissions, session revocation, multi-tenant isolation, or "make our chat secure/compliant to ship." Client-side login wiring itself lives in `cometchat-<family>-core` / `-production`; this skill owns the server + access-control model those depend on.
|
|
16
|
+
|
|
17
|
+
## The auth model (get this right first)
|
|
18
|
+
Three credentials, three homes — mixing them up is the #1 security defect:
|
|
19
|
+
|
|
20
|
+
| Credential | Who holds it | Purpose |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| **Auth Key** | client, **dev only** | quick `login(uid)` in development; can mint a session for ANY user — never ship it |
|
|
23
|
+
| **Auth token** | client, per user | production login with a per-user token — the call is per family (web/Angular/Android/Flutter `loginWithAuthToken(token)`, **iOS `login(authToken:)`**, **React Native `login({ authToken })`**); tied to one UID; revocable |
|
|
24
|
+
| **REST API Key** | **server only** | mint tokens, manage users/roles; full power — never in a client |
|
|
25
|
+
|
|
26
|
+
Production login is always **auth token**, never the Auth Key. Detail + the per-framework client call: `cometchat-<family>-production`.
|
|
27
|
+
|
|
28
|
+
## SSO / OIDC / SAML — through YOUR IdP
|
|
29
|
+
CometChat rides on the identity you already have. The flow is the same whether your IdP is Okta, Auth0, Cognito, Entra ID, Google Workspace, or your own:
|
|
30
|
+
|
|
31
|
+
1. The user signs in through your IdP (SAML/OIDC) — your normal app auth.
|
|
32
|
+
2. Your backend, on that **authenticated session**, maps the IdP subject to a CometChat **UID** (a stable, sanitized id — see `cometchat-migrate-from-*` `toCometChatId` for the alpha-dash/≤100/lowercase rules) and, if the user is new, creates it (`POST {DOCS_BASE}/rest-api/users`, `withAuthToken: true` returns a token in the same call).
|
|
33
|
+
3. Your backend mints an auth token: `POST /v3/users/{uid}/auth_tokens` with the **REST API Key** (`{DOCS_BASE}/rest-api/auth-tokens/create`).
|
|
34
|
+
4. It returns the token to the client over the authenticated request; the client logs in with it via its per-family call (web/Angular/Android/Flutter `loginWithAuthToken(token)`, iOS `login(authToken:)`, React Native `login({ authToken })` — see `cometchat-<family>-production`).
|
|
35
|
+
|
|
36
|
+
**The UID must come from the server session, never a request parameter.** Accepting `?uid=` lets any caller impersonate anyone — the single most common CometChat auth hole.
|
|
37
|
+
|
|
38
|
+
```http
|
|
39
|
+
POST https://{APP_ID}.api-{REGION}.cometchat.io/v3/users/{uid}/auth_tokens
|
|
40
|
+
apikey: {REST_API_KEY} # server-side secret
|
|
41
|
+
content-type: application/json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Session control & revocation
|
|
45
|
+
Auth tokens **do not expire by default** and CometChat keeps a **rolling 100 per user** (oldest auto-archived). For enterprise session control:
|
|
46
|
+
- **Log out one device** → `DELETE /v3/users/{uid}/auth_tokens/{authToken}`.
|
|
47
|
+
- **Kill every session** (deprovisioned employee, suspected compromise) → `DELETE /v3/users/{uid}/auth_tokens` (flush all).
|
|
48
|
+
- **Rotate on privilege change / password reset** → mint a fresh token, flush the rest.
|
|
49
|
+
- **Short-lived sessions** → issue a token per login and flush on logout; don't reuse one token forever.
|
|
50
|
+
Pages: `{DOCS_BASE}/rest-api/auth-tokens/{delete,flush}`.
|
|
51
|
+
|
|
52
|
+
## Access control — RBAC (app-wide) + SBAC (per group)
|
|
53
|
+
CometChat has two layers; an action must pass **both** or the API returns `ERR_PERMISSION_DENIED`:
|
|
54
|
+
|
|
55
|
+
| Layer | Scope | Set via | Use it for |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| **Role (RBAC)** | whole app, one role per user | user create/update (`/rest-api/users`), roles (`/rest-api/roles`) | who may create groups, send messages, start calls, … |
|
|
58
|
+
| **Scope (SBAC)** | inside one group | group membership (`/rest-api/group-members/change-scope`) | `admin` / `moderator` / `participant` within that group |
|
|
59
|
+
|
|
60
|
+
- Define roles server-side via the REST **Roles** endpoint (`POST https://{APP_ID}.api-{REGION}.cometchat.io/v3/roles`; see the docs at `{DOCS_BASE}/rest-api/roles`) — each user gets exactly one; unspecified → `default`.
|
|
61
|
+
- Set the fine-grained permissions per role via **RBAC** (`{DOCS_BASE}/rest-api/rbac-overview`). *(The older per-role `restrict-features` API is **deprecated** — use RBAC.)*
|
|
62
|
+
- Group scopes (`admin`/`moderator`/`participant`) are the SBAC layer; change with the change-scope API.
|
|
63
|
+
Model least privilege: a locked-down `default` role, elevated roles for staff/moderators, plus group scopes for in-group moderation.
|
|
64
|
+
|
|
65
|
+
## Multi-tenant isolation
|
|
66
|
+
- **Strongest:** one CometChat **app per tenant** (separate App ID/keys — full data isolation). Best for regulated or contractual isolation.
|
|
67
|
+
- **Lighter:** one app, tenant-scoped **groups** + a tenant id in user/message **metadata**, enforced by your token server (a user only ever gets a token for their tenant's UID) + RBAC. Cheaper, but isolation is only as strong as your server checks.
|
|
68
|
+
Pick per your compliance bar; document which you chose. Data residency/region selection is `cometchat-compliance`; self-hosting for full sovereignty is `cometchat-self-host`.
|
|
69
|
+
|
|
70
|
+
## Common pitfalls
|
|
71
|
+
1. **Auth Key shipped to the client in production** — it can log in as anyone. Grep the bundle/binary (`cometchat-<family>-production`).
|
|
72
|
+
2. **Token endpoint trusting a client-supplied UID** — impersonation. Derive the UID from the server session.
|
|
73
|
+
3. **"CometChat SSO" misread as CometChat being the IdP** — it isn't; integrate your IdP, then mint a token.
|
|
74
|
+
4. **No revocation on offboarding** — a deprovisioned user keeps chatting until you flush their tokens.
|
|
75
|
+
5. **RBAC assumed but never configured** — every user sits on `default`; define roles + permissions explicitly.
|
|
76
|
+
6. **Using the deprecated `restrict-features`** instead of RBAC.
|
|
77
|
+
7. **REST API Key in client or repo** — server-only; store in a secret manager.
|
|
78
|
+
|
|
79
|
+
## Verify it works
|
|
80
|
+
IdP login → server mints a token from the session UID → the client's per-family auth-token login succeeds (`loginWithAuthToken` / iOS `login(authToken:)` / RN `login({ authToken })`) · a tampered/`?uid=` request is rejected · flushing a user's tokens ends their sessions on every device · a `default`-role user is denied a restricted action (`ERR_PERMISSION_DENIED`) while an elevated role is allowed · no Auth Key or REST API Key anywhere in client code.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cometchat-self-host
|
|
3
|
+
description: "Run CometChat on your own infrastructure — when to self-host, the deployment models (Docker Swarm, Kubernetes, air-gapped), sizing & prerequisites, and how to point your app at the self-hosted instance. CometChat's enterprise differentiator: full data sovereignty. Triggers: 'self-host cometchat', 'on-prem cometchat', 'on premise deployment', 'private cloud chat', 'air-gapped chat', 'run cometchat in our own cloud/VPC', 'data sovereignty', 'point my app at self-hosted cometchat'."
|
|
4
|
+
license: "MIT"
|
|
5
|
+
compatibility: "CometChat on-premise (Docker Swarm 10k–200k MAU · Kubernetes 200k+ / multi-region · air-gapped). Clients: any CometChat UI Kit / SDK pointed at your domain."
|
|
6
|
+
metadata:
|
|
7
|
+
author: "CometChat"
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
tags: "cometchat self-host on-prem on-premise kubernetes docker air-gapped data-sovereignty private-cloud enterprise"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
> **Ground truth:** deployment detail is FETCHED from the live on-premise docs — `{DOCS_BASE}/on-premise-deployment/docker/overview`, `/docker/prerequisites`, `/docker/production-deployment`, `/docker/security`, `/docker/persistence-and-backup`, `/docker/configuration-reference`, `/docker/air-gapped-deployment`, and `/kubernetes/overview` (`DOCS_BASE = https://www.cometchat.com/docs`; append `.md`). On-prem is a licensed enterprise offering — **[contact CometChat sales](https://www.cometchat.com/contact-sales)** for the images, license, and support. The exact **client host-override** field is in the on-prem client/configuration docs — fetch it there; do not guess a setting name.
|
|
13
|
+
|
|
14
|
+
## Use this skill when
|
|
15
|
+
The customer needs the chat backend inside their own perimeter: data sovereignty, an offline/air-gapped network, a regulated industry, a residency clause the SaaS regions can't meet, or fixed-cost infrastructure instead of per-MAU SaaS pricing. Self-hosting (on-premise deployment) is a CometChat enterprise offering — position it as a differentiator, but don't assert what specific competitors do or don't offer without checking their current docs.
|
|
16
|
+
|
|
17
|
+
## Why self-host (vs the SaaS regions)
|
|
18
|
+
- **Data sovereignty** — all data (messages, media, backups) stays on infrastructure you control, which supports your GDPR/HIPAA/SOC 2 and residency obligations (compliance is the customer's to certify; self-hosting removes the SaaS data-location constraint). (Region selection in SaaS is `cometchat-compliance`; self-host is the stronger step.)
|
|
19
|
+
- **Air-gapped / private network** — deploy with no public internet dependency (`/docker/air-gapped-deployment`).
|
|
20
|
+
- **Predictable economics** — fixed infra cost, no per-user SaaS pricing.
|
|
21
|
+
- **Operational control** — your monitoring, your security perimeter, direct component access.
|
|
22
|
+
|
|
23
|
+
## Deployment models (pick by scale)
|
|
24
|
+
| Model | Target | Use when |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| **Docker Swarm** | ~10k–200k MAU, ~20k peak concurrent | most on-prem deployments; lower operational overhead (`/docker/overview`) |
|
|
27
|
+
| **Kubernetes** | 200k+ MAU, multi-region active-active, autoscaling | large scale or multi-region (`/kubernetes/overview`) |
|
|
28
|
+
| **Air-gapped** | offline / isolated networks | export images, transfer, run from a local registry (`/docker/air-gapped-deployment`) |
|
|
29
|
+
|
|
30
|
+
The platform is microservices (WebSocket gateway · Chat API · Moderation · Notifications · Webhooks) over a Kafka event bus, with TiDB (distributed SQL) + MongoDB + Redis and optional S3-compatible object storage. You don't wire these by hand — the deployment scripts do — but size the hosts for them (`/docker/prerequisites`).
|
|
31
|
+
|
|
32
|
+
## Prerequisites & sizing (before you deploy)
|
|
33
|
+
Plan from **MAU and peak concurrent connections (PCC)**: host sizing, OS, storage volumes for the stateful services (databases, Kafka, object storage), and TLS certificates for the load balancer. The full checklist is `{DOCS_BASE}/on-premise-deployment/docker/prerequisites`; follow it rather than improvising capacity.
|
|
34
|
+
|
|
35
|
+
## Deploy (the runbook is the docs, not this file)
|
|
36
|
+
Deployment uses CometChat's automated scripts for consistent, zero-downtime rollouts — `{DOCS_BASE}/on-premise-deployment/docker/production-deployment`. Domains/environment values are set per `/docker/configuration-reference` (+ the domain-update guide). Do not hand-assemble the compose/stack; drive the documented scripts.
|
|
37
|
+
|
|
38
|
+
## Point your app at the self-hosted instance
|
|
39
|
+
Clients reach on-prem over **HTTPS + WebSocket** through your load balancer / NGINX (TLS-terminated). In the app, the CometChat init settings must target **your domain** instead of the SaaS region endpoint — the exact host/region-override field is in the on-prem client-integration + `configuration-reference` docs; **fetch it there and set it**, then keep everything else (App ID, login flow) the same. Every family's init lives in `cometchat-<family>-core`; only the host target changes for on-prem. Verify the app connects to your domain (not `*.cometchat.io`) in the network tab.
|
|
40
|
+
|
|
41
|
+
## Security & operations
|
|
42
|
+
- **Auth**: on-prem uses JWT-based authentication with RSA key pairs — only authorized users reach the platform (`{DOCS_BASE}/on-premise-deployment/docker/security`). Combine with the app-level access model in `cometchat-security`.
|
|
43
|
+
- **Network**: keep data stores on the private overlay; expose only the load balancer; enforce TLS end-to-end.
|
|
44
|
+
- **Backups & DR**: automated backups with point-in-time recovery and retention aligned to your compliance policy (`/docker/persistence-and-backup`) — this is where you own the retention lifecycle `cometchat-compliance` defers to.
|
|
45
|
+
- **Monitoring**: the stack ships Prometheus + Grafana + Loki; wire alerts to your on-call.
|
|
46
|
+
|
|
47
|
+
## Common pitfalls
|
|
48
|
+
1. **Treating on-prem as self-serve** — it's a licensed offering; start with sales for images + license + support.
|
|
49
|
+
2. **Under-sizing** — plan hosts from MAU/PCC via the prerequisites, not a guess.
|
|
50
|
+
3. **Hand-writing the stack** — use the documented deployment scripts; drift breaks upgrades.
|
|
51
|
+
4. **App still pointing at `*.cometchat.io`** — set the client host override to your domain, or you're on SaaS, not on-prem.
|
|
52
|
+
5. **Guessing the host-override field** — fetch the exact setting from the on-prem client docs.
|
|
53
|
+
6. **No TLS / exposed data stores** — terminate TLS at the LB and keep TiDB/Mongo/Redis/Kafka on the private network.
|
|
54
|
+
|
|
55
|
+
## Verify it works
|
|
56
|
+
The stack deploys via the documented scripts and health checks pass · the app connects to YOUR domain over HTTPS/WSS (confirmed in the network tab), logs in, sends and receives · JWT/RSA auth is enforced · data stores are private + TLS everywhere · backups run and a restore is tested · Grafana shows the services healthy.
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"video_stream_modes.dart",
|
|
190
190
|
"video_stream_positions.dart"
|
|
191
191
|
],
|
|
192
|
-
"note": "All six were already in internalOnlyExcluded — never reachable from the barrel — so deleting them changed nothing here. `CallType` is the same phantom
|
|
192
|
+
"note": "All six were already in internalOnlyExcluded — never reachable from the barrel — so deleting them changed nothing here. `CallType` is the same phantom internal issue #183 filed on iOS."
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
}
|
|
@@ -62,14 +62,17 @@ const nestedKey = (b, k) => (b.match(new RegExp("^\\s+" + k + ":\\s*(.+)$", "m")
|
|
|
62
62
|
// named `cometchat-<slug>` and are routed via peers.yaml's `gate:` / top-level pointers
|
|
63
63
|
// (the entry router ALWAYS routes to the gate first), NOT via a peer's `skills:` list —
|
|
64
64
|
// so they must be recognized here instead of failing the per-platform grammar.
|
|
65
|
-
const CROSS_FAMILY_SLUGS = new Set(["a11y", "i18n", "onboarding"]);
|
|
65
|
+
const CROSS_FAMILY_SLUGS = new Set(["a11y", "i18n", "onboarding", "security", "compliance", "self-host", "moderation", "audit", "analytics"]);
|
|
66
|
+
// Competitor-migration skills are cross-family too (one per vendor, installed for every family):
|
|
67
|
+
// `cometchat-migrate-from-<vendor>`, routed via peers.yaml `migrations:` (NAMING.md).
|
|
68
|
+
const COMPETITOR_MIGRATION = /^cometchat-migrate-from-([a-z0-9]+)$/;
|
|
66
69
|
|
|
67
70
|
// The gates grafted below were authored for the ANGULAR family + the shared skills. Other
|
|
68
71
|
// families are maintained elsewhere; applied pack-wide they turned this repo's 15
|
|
69
72
|
// pre-existing problems into 123 by firing on 40+ android/ios/flutter/rn skills. A gate we
|
|
70
73
|
// wrote must not fail a family we do not own — same scoping the token and fence gates need.
|
|
71
74
|
const OWNED_SKILL = (d) =>
|
|
72
|
-
/^cometchat-angular-v5-/.test(d) || d === "cometchat" || d === "cometchat-onboarding";
|
|
75
|
+
/^cometchat-angular-v5-/.test(d) || d === "cometchat" || d === "cometchat-onboarding" || COMPETITOR_MIGRATION.test(d);
|
|
73
76
|
|
|
74
77
|
// Parse the capability slugs each peer routes to (peers.yaml `skills: [...]`), plus the
|
|
75
78
|
// platform-neutral routing pointers (`gate:` and any bare cross-family targets).
|
|
@@ -86,6 +89,14 @@ function routedSlugs() {
|
|
|
86
89
|
// `gate: cometchat-onboarding` (and any future bare cross-family pointer) → routed.
|
|
87
90
|
const gate = (y.match(/^\s*gate:\s*(\S+)/m) || [])[1];
|
|
88
91
|
if (gate) neutral.add(gate.trim());
|
|
92
|
+
// `migrations:` entries (`skill: cometchat-migrate-from-<vendor>`) → routed, platform-neutral.
|
|
93
|
+
const mig = (y.match(/^migrations:\s*\n([\s\S]*?)(?=^\S)/m) || [])[1] || "";
|
|
94
|
+
for (const m of mig.matchAll(/^\s*skill:\s*(\S+)/gm)) neutral.add(m[1].trim());
|
|
95
|
+
// `enterprise:` cross-family skills (bare `- cometchat-<slug>`) → routed, platform-neutral.
|
|
96
|
+
const ent = (y.match(/^enterprise:\s*\n([\s\S]*?)(?=^\S)/m) || [])[1] || "";
|
|
97
|
+
for (const m of ent.matchAll(/^\s*-\s*(\S+)/gm)) neutral.add(m[1].trim());
|
|
98
|
+
const cf = (y.match(/^crossFamily:\s*\n([\s\S]*?)(?=^\S)/m) || [])[1] || "";
|
|
99
|
+
for (const m of cf.matchAll(/^\s*-\s*(\S+)/gm)) neutral.add(m[1].trim());
|
|
89
100
|
return { platforms, slugs, neutral };
|
|
90
101
|
}
|
|
91
102
|
|
|
@@ -109,8 +120,10 @@ const PLATFORMS = ["react-native", "react", "angular", "android", "flutter", "io
|
|
|
109
120
|
// sanctions for react-native specifically). So every correctly-named RN skill was rejected.
|
|
110
121
|
// Same class as the six --family hardcodes (AUDIT-091/087): a rule written for one family.
|
|
111
122
|
function classify(dir) {
|
|
112
|
-
const c = dir.match(/^cometchat-([a-z0-9]+)$/);
|
|
123
|
+
const c = dir.match(/^cometchat-([a-z0-9-]+)$/);
|
|
113
124
|
if (c && CROSS_FAMILY_SLUGS.has(c[1])) return { crossFamily: true, slug: c[1] };
|
|
125
|
+
const v = dir.match(COMPETITOR_MIGRATION);
|
|
126
|
+
if (v) return { crossFamily: true, slug: `migrate-from-${v[1]}` };
|
|
114
127
|
for (const p of PLATFORMS) {
|
|
115
128
|
let m = dir.match(new RegExp(`^cometchat-${p}-(v\\d+)-([a-z][a-z-]*)$`));
|
|
116
129
|
if (m) return { platform: p, major: m[1], slug: m[2] };
|
|
@@ -146,7 +159,7 @@ function lintSkill(dir, routed) {
|
|
|
146
159
|
// whichever family core the plan/context names). Routed via a neutral pointer
|
|
147
160
|
// (peers.yaml `gate:` / entry), not a peer's `skills:` list.
|
|
148
161
|
if (!routed.neutral.has(dir)) {
|
|
149
|
-
errs.push(`cross-family skill "${dir}" not routed in peers.yaml (add it as gate
|
|
162
|
+
errs.push(`cross-family skill "${dir}" not routed in peers.yaml (add it as gate:, a neutral pointer, or a migrations: skill)`);
|
|
150
163
|
}
|
|
151
164
|
} else {
|
|
152
165
|
// Companion block — required on every non-core per-platform skill (BUILD-ORDER DRY rule).
|
|
@@ -317,10 +330,16 @@ function gateOsThemeRecipe() {
|
|
|
317
330
|
// reference initFromSettings, and the canonical lifecycle recipe must not use the classic init(.
|
|
318
331
|
function gateInitTelemetry() {
|
|
319
332
|
const errs = [];
|
|
320
|
-
const
|
|
321
|
-
.filter((d) => d.isDirectory()
|
|
333
|
+
const allDirs = readdirSync(SKILLS_DIR, { withFileTypes: true })
|
|
334
|
+
.filter((d) => d.isDirectory())
|
|
322
335
|
.map((d) => d.name);
|
|
323
|
-
|
|
336
|
+
// Skills that teach an init recipe: UI-Kit cores AND the headless / SDK-fallback skills (`-sdk`).
|
|
337
|
+
// Both must attribute via initFromSettings, never the classic builder init. The check was
|
|
338
|
+
// originally core-only, which let a `-sdk` fallback skill (cometchat-react-native-sdk) ship the
|
|
339
|
+
// classic `CometChat.init(APP_ID, settings)` in its golden path — a `-sdk` skill is exactly the
|
|
340
|
+
// SDK-fallback surface (e.g. rn-uikit-v5.sdkSkill), so it must obey the same rule. (AUDIT-084; ENG-39197.)
|
|
341
|
+
const initSkills = allDirs.filter((d) => d.endsWith("-core") || d.endsWith("-sdk"));
|
|
342
|
+
for (const dir of initSkills) {
|
|
324
343
|
for (const rel of [`${dir}/references/lifecycle.md`, `${dir}/SKILL.md`]) {
|
|
325
344
|
const p = join(SKILLS_DIR, rel);
|
|
326
345
|
if (!existsSync(p)) continue;
|
|
@@ -334,6 +353,10 @@ function gateInitTelemetry() {
|
|
|
334
353
|
);
|
|
335
354
|
}
|
|
336
355
|
}
|
|
356
|
+
}
|
|
357
|
+
// UI-Kit cores only: the baked lifecycle recipe must not default to the classic CometChatUIKit.init(.
|
|
358
|
+
const coreDirs = allDirs.filter((d) => d.endsWith("-core"));
|
|
359
|
+
for (const dir of coreDirs) {
|
|
337
360
|
const lc = join(SKILLS_DIR, `${dir}/references/lifecycle.md`);
|
|
338
361
|
if (existsSync(lc) && /CometChatUIKit\.init\(/.test(readFileSync(lc, "utf8"))) {
|
|
339
362
|
errs.push(
|
|
@@ -55,7 +55,11 @@ for (const rel of TOOLS) {
|
|
|
55
55
|
const NEUTRAL = [
|
|
56
56
|
...(existsSync(join(ROOT, "bin")) ? readdirSync(join(ROOT, "bin")).filter((f) => f.endsWith(".mjs")).map((f) => `bin/${f}`) : []),
|
|
57
57
|
"RULES.md",
|
|
58
|
-
|
|
58
|
+
// The router, the gate, and the competitor-migration skills (peers.yaml `migrations:`) are all
|
|
59
|
+
// installed for every family — each is a platform-neutral surface.
|
|
60
|
+
...["cometchat", "cometchat-onboarding",
|
|
61
|
+
...(existsSync(join(ROOT, "skills")) ? readdirSync(join(ROOT, "skills")).filter((d) => /^cometchat-migrate-from-[a-z0-9]+$/.test(d)) : []),
|
|
62
|
+
].flatMap((d) => {
|
|
59
63
|
const dir = join(ROOT, "skills", d);
|
|
60
64
|
if (!existsSync(dir)) return [];
|
|
61
65
|
const out = [`skills/${d}/SKILL.md`];
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# i18n, RTL, accessibility (React v7)
|
|
2
|
-
|
|
3
|
-
The UI Kit handles all three out of the box; careless customization breaks them.
|
|
4
|
-
|
|
5
|
-
## RTL
|
|
6
|
-
Reads `dir="rtl"` from the document root — components flip automatically (bubbles mirror, avatars swap, icons rotate). Test with `<html dir="rtl">`. Custom views MUST use logical properties (`margin-inline-start`, `padding-inline-end`) or they break RTL.
|
|
7
|
-
|
|
8
|
-
## i18n — localization works via the provider; NEVER render a raw key
|
|
9
|
-
`CometChatProvider` **auto-wires localization** (it renders `LocaleProvider` internally, `locale` prop) — the kit's ~40 built-in languages load out of the box (default `en-us`). You do NOT manually init for the default language.
|
|
10
|
-
- **Non-default language:** set the `locale` prop on `CometChatProvider` (`<CometChatProvider locale="fr">`) — that's the v7 way to switch language. `init` / `setCurrentLanguage` / `getCurrentLanguage` / `addTranslation` are **INSTANCE** methods on `CometChatLocalize`, NOT statics — calling e.g. `CometChatLocalize.setCurrentLanguage(...)` is a TS2339 error. Reach the live instance with `CometChatLocalize.getSharedInstance()` (registered by `CometChatUIKit.init*` / the provider) and configure it there — `getSharedInstance()?.init({ translationsForLanguage, timezone, calendarObject, fallbackLanguage, … })`. **Don't `new CometChatLocalize(...)`**: the provider reads only the shared instance, so a constructed one isn't wired to the UI. Language stays on the `locale` prop (default `"en-us"`) — the provider applies it on mount/change, overriding an earlier `init({ language })`.
|
|
11
|
-
- **Custom strings:** `CometChatLocalize.getSharedInstance()?.addTranslation(resources)` where `resources` is **nested per-language** `Record<lang, Record<key, string>>` (NOT a flat map; verified vs 7.1.0). Runtime hook: `useLocale()` → `{ getLocalizedString, language }`.
|
|
12
|
-
- **`getLocalizedString(key)` returns the RAW KEY on a miss** (verified in the kit — `translate` falls back to `return key`). So a snake_case token in the UI (`group_info`, `add_members`, `delete_and_exit`, `view_members`) is a **localization failure**: a wrong/removed key, a custom language set without its translations, or — the #1 cause — **custom UI that rendered the key literally as a label.**
|
|
13
|
-
- **NEVER hardcode a localization key as text.** Use the kit component (it localizes itself) or `useLocale().getLocalizedString(key)` — never `<button>group_info</button>`.
|
|
14
|
-
- Don't invent keys; verify against the localization docs (`.md` twin, never the `.d.ts`). **v6→v7 changed some keys**, so a stale v6 key now misses and shows the raw string.
|
|
15
|
-
|
|
16
|
-
## Accessibility
|
|
17
|
-
Defaults ship: `aria-label` on icon buttons; `role="listbox"`/`option` on lists; Tab/Enter/Esc keyboard nav; focus management on thread open/close. When customizing:
|
|
18
|
-
1. Icon-only button → add `aria-label="<verb>"`.
|
|
19
|
-
2. List item → keep `role="option"` + `aria-selected`.
|
|
20
|
-
3. Composer → keep an accessible `<label>` + `Enter`/`Shift+Enter`.
|
|
21
|
-
4. Modal → trap focus, restore on close, `role="dialog"` + `aria-modal="true"` + labelled heading.
|
|
22
|
-
5. Theming → verify text contrast ≥ 4.5:1. Deep custom views own their own a11y; test with a screen reader + keyboard.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# troubleshooting — CometChat React v7: symptom → cause → fix
|
|
2
|
-
|
|
3
|
-
The fast symptom-table for a broken integration. Each row is a REAL failure mode, baked (don't fetch docs); deeper detail is cross-linked to the sibling reference.
|
|
4
|
-
|
|
5
|
-
## The table
|
|
6
|
-
| Symptom (what the user sees) | Root cause | Fix |
|
|
7
|
-
|---|---|---|
|
|
8
|
-
| **Blank / empty screen, no errors** | Component rendered BEFORE `init()`+`login()` resolved, or wrong Region / env prefix so init silently fails | Gate render on `getLoggedInUser()` (`init→login→render` is invariant); verify Region matches the Dashboard app + env prefix matches the bundler. `lifecycle.md` + `setup-credentials.md`. |
|
|
9
|
-
| **`window is not defined` / `document is not defined`** | SSR — the kit touches browser globals during server render (Next RSC, Astro, React-Router) | Make the chat tree client-only: Next `"use client"` + `dynamic(…, { ssr:false })`; Astro `client:only="react"`; RR guard `typeof window`. `ssr.md`. |
|
|
10
|
-
| **Chat renders as a ~0px sliver / crammed top-left** | The container has no resolved height/width — kit components are `height:100%`/flex-fill and collapse in a content-driven box (static collapse) | Content-INDEPENDENT height **and** width: full-page `100dvh`/`100%`; embedded a fixed height or sized grid/flex cell. **Columns need height + `min-height:0` too**, not just the root. `layout.md` + `anti-patterns.md` #8. |
|
|
11
|
-
| **Chat is small while the list loads, then GROWS to full size** (reflow) | Box is content-driven, not pinned (ancestor chain not `height:100%`, or `min-height`/`auto`, or an unsized wrapper) — the kit fills "nothing" and grows as content arrives | Pin independent of content: `html,body,#root{height:100%;margin:0}` + `100dvh` (never `min-height`/`auto`) + `min-height:0` columns; let the kit's own `loadingView`/`emptyView` fill the pinned box. `layout.md` (AUDIT-023). |
|
|
12
|
-
| **Snake_case tokens** (`group_info`, `add_members`) instead of labels | Localization key MISS — `getLocalizedString` returns the raw key; v7 namespaces sample strings under `sample_` so v6 keys miss | Map to the v7 key (`group_info`→`sample_group_info`) or the INSTANCE method `CometChatLocalize.getSharedInstance()?.addTranslation(...)`; look up the EXACT key in the kit source / docs — never guess. `i18n-rtl-a11y.md` + migration §7. |
|
|
13
|
-
| **Usernames centered / conversations header keeps growing** | Host GLOBAL CSS leaking into the `.cometchat` subtree (global `text-align:center`, a centering reset, or `flex:1` on a kit ancestor — often Tailwind base) | Scope global styles away from the kit root; never override the kit's internal classes (its defaults are correct). Customize via theme vars + view slots only. `anti-patterns.md` #12. |
|
|
14
|
-
| **Kit overlays (menus, emoji, call screen) clipped / mis-positioned** | A `transform`/`filter`/`backdrop-filter` on a wrapper above the kit traps its `position:fixed` overlays | Remove the transform/filter from the chat wrapper; animate `left`/`right`/width instead. `anti-patterns.md` #8/#11. |
|
|
15
|
-
| **`version_conflict` on `detect`, or two kits behaving oddly** | The project declares a non-v7 kit major (v5/v6), or two cohorts at once | STOP. Reconcile: upgrade to v7 (migration skill for v6→v7), load the matching-version skills, or remove the extra cohort. Never mix majors. `RULES.md`. |
|
|
16
|
-
| **`login()` fails / "user not found"** | Logging in a UID that doesn't exist (a guessed sample like `superhero1`, not seeded) | Use a UID that EXISTS: ask, or Dashboard → Users (fresh apps seed `cometchat-uid-1`…); create one if none fits. Prod → per-user auth token + `loginWithAuthToken`. `setup-credentials.md` §6. |
|
|
17
|
-
| **Roster lists render every row TWICE + ~30 "duplicate key" errors** (dev only) | React **StrictMode** (default in fresh Vite) double-invokes effects; roster drop-ins `CometChatUsers`/`CometChatGroups`/`CometChatGroupMembers` double-append (kit de-dupe gap; `CometChatConversations` unaffected). Dev-only. | A StrictMode DEV artifact — gone in `vite build`/prod. Do NOT remove StrictMode to "fix" it; verify the roster in a prod build. Kit issue (report upstream). AUDIT-062/065. |
|
|
18
|
-
| **`TS6133` "declared but never read" on a `CometChat` import** | The `CometChat` SDK is an ambient global — importing the namespace only for TYPE use trips `noUnusedLocals`+`verbatimModuleSyntax` (Vite React-TS) | Import only for VALUE use (`instanceof CometChat.User`, `new CometChat.*RequestBuilder`). Type-only → reference `CometChat.User`/`.Group` with NO import (resolves ambiently). `dependencies.md` (AUDIT-007). |
|
|
19
|
-
| **StrictMode logs a double init / double login** (dev) | React 18 StrictMode double-invokes effects; an unguarded `init()`/`login()` runs twice | Guard with an init-once ref + a concurrent-login guard (`ensureLoggedIn`). `lifecycle.md`. |
|
|
20
|
-
| **Theme ignores the OS dark/light setting** | Kit defaults to `light`, no `theme="system"` | Sync `CometChatProvider theme=` to `prefers-color-scheme` yourself. `theming.md` (AUDIT-004). |
|
|
21
|
-
| **A default-on control does nothing** (search filters nothing, "Reply in Thread" no-ops) | The drop-in renders a live-looking affordance that's INERT until the host wires it (`needs_stitching`) | Wire the destination (`onSearchBarClicked`→`CometChatSearch`; `onThreadRepliesClick`→thread) OR hide it (`showSearchBar={false}`/`hideReplyInThreadOption`). Never dead-end. Features skill. |
|
|
22
|
-
| **Search wired but returns nothing (HTTP 402)** | `CometChatSearch`'s server call returns `402 Payment Required` until Search is enabled on the plan/Dashboard | TELL the user: wiring alone yields nothing — enable Search in the Dashboard / upgrade. `features.json` `message-search`. |
|
|
23
|
-
| **Call buttons hidden / calls never ring** | Calling not enabled, or the calls SDK isn't installed | Install `@cometchat/calls-sdk-javascript@5` (not bundled) AND turn calling ON: `uiKit:{ callsSDK:{} }` in `CometChatUIKit.initFromSettings`. Both required; groups don't ring (join model). Calls skill. |
|
|
24
|
-
|
|
25
|
-
## When it's NOT in the table
|
|
26
|
-
- **Prop/signature question** → fetch the component's `.md` twin via `docs-map.md`; never read `.d.ts` or answer from memory.
|
|
27
|
-
- **A feature renders empty** → the extension likely isn't enabled in the Dashboard (features skill "Verify it works").
|
|
28
|
-
- **Still stuck** → check the console + network tab (a `4xx` on a CometChat endpoint = auth/plan/config, not a code bug), confirm App ID/Region/Auth Key in the env, and re-verify the detected framework/bundler + prefix by reading the project.
|