@nexalink/carecompass-sdk 0.1.0-beta.8 → 0.2.0-beta.11
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/CHANGELOG.md +37 -0
- package/LICENSE +2 -1
- package/README.md +150 -39
- package/RELEASE.md +65 -0
- package/RUNTIME_SECURITY_AUDIT.md +180 -0
- package/SECURITY_AUDIT.md +78 -0
- package/TELEMETRY.md +129 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +377 -41
- package/dist/client.d.ts +4 -2
- package/dist/client.js +163 -24
- package/dist/component.js +41 -2
- package/dist/credentials.js +4 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -2
- package/dist/mount.js +10 -2
- package/dist/schema.d.ts +3 -1
- package/dist/schema.js +79 -5
- package/dist/snippet.js +22 -4
- package/dist/telemetry.d.ts +71 -0
- package/dist/telemetry.js +180 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +3 -0
- package/package.json +37 -9
- package/dist/cli.js.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/component.js.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mount.js.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/snippet.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@nexalink/carecompass-sdk` are documented in this file.
|
|
4
|
+
|
|
5
|
+
This project uses [release-please](https://github.com/googleapis/release-please) and conventional commits to prepare changelog and version updates.
|
|
6
|
+
|
|
7
|
+
## [0.2.0-beta.11](https://github.com/nexalink-care/carecompass-sdk/compare/v0.1.0-beta.11...v0.2.0-beta.11) (2026-06-07)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* baa self-serve ([3ff6d66](https://github.com/nexalink-care/carecompass-sdk/commit/3ff6d662dc83215b85615515eec01c54600fb9ea))
|
|
13
|
+
* baa self-serve (CARE-155) ([92c11df](https://github.com/nexalink-care/carecompass-sdk/commit/92c11df5dfc85df195788f5b5aea03112c4c2420))
|
|
14
|
+
* cli update ([99ef0e5](https://github.com/nexalink-care/carecompass-sdk/commit/99ef0e52166b519d8982bd67997fae4a0f1a4bb1))
|
|
15
|
+
* implement telemetry (CARE-158) ([6337fd7](https://github.com/nexalink-care/carecompass-sdk/commit/6337fd791dc8bbf2192f2b683dbd2d0ef3bbf03a))
|
|
16
|
+
* initial commit ([5369c40](https://github.com/nexalink-care/carecompass-sdk/commit/5369c409361be39caaa84db8d3ab1f98f5aec134))
|
|
17
|
+
* initial commit ([26ec799](https://github.com/nexalink-care/carecompass-sdk/commit/26ec79928226e98235cd8c42a348a9e070b948c9))
|
|
18
|
+
* necessary comments ([127c834](https://github.com/nexalink-care/carecompass-sdk/commit/127c8346bc865c5054b02490c890a53bd03db97a))
|
|
19
|
+
* necessary comments ([d7f0d6b](https://github.com/nexalink-care/carecompass-sdk/commit/d7f0d6b7525b9e6282961b8172415e514305bed0))
|
|
20
|
+
* security audit ([8115fe2](https://github.com/nexalink-care/carecompass-sdk/commit/8115fe2a75d522f2560ec1ec0f5d9ea1eb1feba4))
|
|
21
|
+
* security audit ([0505ae1](https://github.com/nexalink-care/carecompass-sdk/commit/0505ae11937ab15d51b633c782494fe6af468217))
|
|
22
|
+
* telemetry ([8f4dff3](https://github.com/nexalink-care/carecompass-sdk/commit/8f4dff3efc80e6e08ad6f0d19b12b7f85688b406))
|
|
23
|
+
* telemetry update ([cd15546](https://github.com/nexalink-care/carecompass-sdk/commit/cd15546a756abfa30bf18705d204e9a21d12822f))
|
|
24
|
+
* update cli flow ([69c55d5](https://github.com/nexalink-care/carecompass-sdk/commit/69c55d58d55ad64281384254852da468e20214f4))
|
|
25
|
+
* updated init flow ([4bd0acf](https://github.com/nexalink-care/carecompass-sdk/commit/4bd0acfd08255b4614fb04b1d5c92b163fb8bcee))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* whitespace issue ([764c7fc](https://github.com/nexalink-care/carecompass-sdk/commit/764c7fc23de945f4e358c944312c06c3567b0e5e))
|
|
31
|
+
|
|
32
|
+
## [0.1.0-beta.11] - 2026-05-30
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Initial beta SDK package with React embed, vanilla mount helper, CLI setup flow, config validation, snippet generation, and local diagnostics.
|
|
37
|
+
- Supply-chain and runtime security audit documentation for payer deployments.
|
package/LICENSE
CHANGED
|
@@ -9,7 +9,8 @@ written agreement with Nexalink Health, Inc.
|
|
|
9
9
|
|
|
10
10
|
Authorized Nexalink customers and implementation partners may install and use
|
|
11
11
|
this package solely to evaluate, integrate, test, and operate CareCompass embed
|
|
12
|
-
experiences for
|
|
12
|
+
experiences for customer-approved healthcare deployments using Nexalink-issued
|
|
13
|
+
credentials.
|
|
13
14
|
|
|
14
15
|
You may not copy, modify, publish, distribute, sell, sublicense, reverse
|
|
15
16
|
engineer, or use this software to provide a competing service except where
|
package/README.md
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
# CareCompass
|
|
1
|
+
# CareCompass Healthcare Embed SDK
|
|
2
2
|
|
|
3
|
-
`@nexalink/carecompass-sdk` helps
|
|
3
|
+
`@nexalink/carecompass-sdk` helps healthcare organizations embed a branded CareCompass chat experience in their own websites and applications. It includes a React component, a vanilla JavaScript mount helper, shared configuration validation, and a CLI for setup, validation, snippet generation, and local diagnostics.
|
|
4
4
|
|
|
5
|
-
CareCompass lets
|
|
5
|
+
CareCompass lets healthcare teams offer member-facing navigation support while keeping LLM inference behind Nexalink-hosted APIs. The integrating organization controls the placement, branding, theme, labels, support links, allowed origins, and approved prompt configuration. Nexalink controls account validation, API-key enforcement, embed-key authorization, usage tracking, and the hosted model path.
|
|
6
6
|
|
|
7
|
-
This package is publicly installable for developer convenience, but
|
|
7
|
+
This package is publicly installable for developer convenience, but live regulated use requires Nexalink onboarding, BAA coverage where PHI may be involved, and Nexalink-issued API credentials.
|
|
8
8
|
|
|
9
9
|
## Who This Is For
|
|
10
10
|
|
|
11
|
-
This SDK is for enterprise healthcare teams that want to add CareCompass to
|
|
11
|
+
This SDK is for enterprise healthcare teams that want to add CareCompass to their own frontend without building a model gateway, prompt validation layer, key-management flow, or token-metering pipeline.
|
|
12
12
|
|
|
13
13
|
Typical users include:
|
|
14
14
|
|
|
15
|
-
- payer
|
|
15
|
+
- payer, provider, employer-benefits, care-navigation, and digital-health teams embedding CareCompass in a member or patient site
|
|
16
16
|
- implementation engineers configuring staging and production deployments
|
|
17
17
|
- technical operators validating origins, branding, and prompt policy
|
|
18
|
-
- non-technical
|
|
18
|
+
- non-technical customer admins issuing SDK keys from the Nexalink portal
|
|
19
19
|
|
|
20
20
|
## Account Required
|
|
21
21
|
|
|
22
|
-
You need a Nexalink
|
|
22
|
+
You need a Nexalink account with SDK access before using the SDK beyond package installation. For deployments that may involve PHI, a signed BAA and approved credentials are required before live use.
|
|
23
23
|
|
|
24
24
|
The account is required because Nexalink validates:
|
|
25
25
|
|
|
26
|
-
- the payer ID
|
|
26
|
+
- the customer or payer ID
|
|
27
27
|
- the secret SDK API key
|
|
28
28
|
- the public browser embed key
|
|
29
29
|
- the deployment environment
|
|
@@ -31,15 +31,35 @@ The account is required because Nexalink validates:
|
|
|
31
31
|
- the approved prompt configuration
|
|
32
32
|
- API usage and token counts for future metered billing
|
|
33
33
|
|
|
34
|
-
API keys are issued in the Nexalink
|
|
34
|
+
API keys are issued in the Nexalink portal under the CareCompass SDK section.
|
|
35
|
+
For first-time onboarding, a tenant owner or admin executes the canonical BAA
|
|
36
|
+
from the portal BAA page before generating the first key. The secret API key is
|
|
37
|
+
shown once and should be stored locally by the developer. It should never be
|
|
38
|
+
committed to source control or placed in browser code.
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
### API Key Vs Embed Key
|
|
41
|
+
|
|
42
|
+
CareCompass uses two different keys with different security expectations:
|
|
43
|
+
|
|
44
|
+
- **API key**: a secret credential for trusted setup and server-side/CLI
|
|
45
|
+
workflows. Use it to authenticate actions such as signing in during `init` and
|
|
46
|
+
creating or managing SDK access. Never include it in browser code, generated
|
|
47
|
+
embed HTML, frontend config, or source control.
|
|
48
|
+
- **Embed key**: a public browser-facing identifier for the CareCompass embed.
|
|
49
|
+
It is safe to include in `carecompass.config.json` and generated snippets. It
|
|
50
|
+
identifies the payer, environment, and embed client for runtime requests, but
|
|
51
|
+
it is not a secret and should not be treated as proof of identity on its own.
|
|
52
|
+
|
|
53
|
+
Start onboarding with:
|
|
37
54
|
|
|
38
55
|
```bash
|
|
39
|
-
npx @nexalink/carecompass-sdk
|
|
56
|
+
npx @nexalink/carecompass-sdk init
|
|
40
57
|
```
|
|
41
58
|
|
|
42
|
-
The CLI
|
|
59
|
+
The CLI routes developers without accounts to the configured signup path,
|
|
60
|
+
validates the API key with Nexalink, stores it locally only after successful
|
|
61
|
+
sign-in, and generates the SDK config. BAA execution happens in the Nexalink web
|
|
62
|
+
app before API key creation.
|
|
43
63
|
|
|
44
64
|
## Install And Run
|
|
45
65
|
|
|
@@ -47,15 +67,14 @@ Use any common JavaScript package manager. For first-time testing, the simplest
|
|
|
47
67
|
path is to run each command with `npx`.
|
|
48
68
|
|
|
49
69
|
```bash
|
|
50
|
-
npx @nexalink/carecompass-sdk
|
|
51
|
-
npx @nexalink/carecompass-sdk init --payer-id acme-health --origin https://members.acme-health.com
|
|
70
|
+
npx @nexalink/carecompass-sdk init --account-type developer --api-key <nexalink-api-key> --payer-id acme-health --origin https://members.acme-health.com
|
|
52
71
|
npx @nexalink/carecompass-sdk validate --config carecompass/carecompass.config.json
|
|
53
72
|
npx @nexalink/carecompass-sdk doctor --config carecompass/carecompass.config.json
|
|
54
73
|
```
|
|
55
74
|
|
|
56
|
-
`npx` does not permanently install a `carecompass` shell command.
|
|
57
|
-
`npx
|
|
58
|
-
|
|
75
|
+
`npx` does not permanently install a `carecompass` shell command. Keep using
|
|
76
|
+
`npx @nexalink/carecompass-sdk <command>` for init, validate, snippet, and
|
|
77
|
+
doctor.
|
|
59
78
|
|
|
60
79
|
Package-manager equivalents:
|
|
61
80
|
|
|
@@ -83,17 +102,15 @@ carecompass init --payer-id acme-health --origin https://members.acme-health.com
|
|
|
83
102
|
|
|
84
103
|
## CLI Commands
|
|
85
104
|
|
|
86
|
-
### `
|
|
87
|
-
|
|
88
|
-
Stores your secret Nexalink API key locally so the other SDK commands can validate your payer configuration.
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
npx @nexalink/carecompass-sdk login --api-key <nexalink-api-key>
|
|
92
|
-
```
|
|
105
|
+
### `init`
|
|
93
106
|
|
|
94
|
-
|
|
107
|
+
Runs the complete first-time onboarding flow:
|
|
95
108
|
|
|
96
|
-
|
|
109
|
+
- routes users without accounts to the configured signup path
|
|
110
|
+
- validates the API key with Nexalink before continuing
|
|
111
|
+
- stores the secret Nexalink API key locally
|
|
112
|
+
- generates the SDK config, prompt starter, embed page, iframe, and setup guide
|
|
113
|
+
with only public embed configuration
|
|
97
114
|
|
|
98
115
|
Creates a `carecompass` folder with all generated SDK files in one place:
|
|
99
116
|
|
|
@@ -103,7 +120,17 @@ Creates a `carecompass` folder with all generated SDK files in one place:
|
|
|
103
120
|
- `carecompass/carecompass-iframe.html`
|
|
104
121
|
- `carecompass/README.md`
|
|
105
122
|
|
|
106
|
-
|
|
123
|
+
Credentials are stored at `~/.nexalink/carecompass/credentials.json` by
|
|
124
|
+
default. You can also set `CARECOMPASS_API_KEY` in your shell or CI environment.
|
|
125
|
+
The generated config contains payer-facing configuration only. It does not
|
|
126
|
+
contain the secret API key. The embed HTML and iframe are generated
|
|
127
|
+
automatically during `init`; you do not need to run a separate snippet command
|
|
128
|
+
for the first setup.
|
|
129
|
+
|
|
130
|
+
For scripted setup, pass `--account-type developer`. The developer signup route
|
|
131
|
+
can be configured with `--developer-signup-url` or
|
|
132
|
+
`CARECOMPASS_DEVELOPER_SIGNUP_URL`. By default, that route is
|
|
133
|
+
`https://www.nexalink.care/developer/signup`.
|
|
107
134
|
|
|
108
135
|
By default, generated HTML is bundler-friendly and imports the package as
|
|
109
136
|
`@nexalink/carecompass-sdk`, which works with Parcel, Vite, Next.js, and similar
|
|
@@ -112,16 +139,18 @@ demo that is not processed by Parcel or another bundler, add
|
|
|
112
139
|
`--snippet-mode cdn`.
|
|
113
140
|
|
|
114
141
|
```bash
|
|
115
|
-
npx @nexalink/carecompass-sdk init --payer-id acme-health --origin https://members.acme-health.com
|
|
116
|
-
npx @nexalink/carecompass-sdk init --snippet-mode cdn --payer-id acme-health --origin https://members.acme-health.com
|
|
142
|
+
npx @nexalink/carecompass-sdk init --account-type developer --api-key <nexalink-api-key> --payer-id acme-health --origin https://members.acme-health.com
|
|
143
|
+
npx @nexalink/carecompass-sdk init --account-type developer --snippet-mode cdn --payer-id acme-health --origin https://members.acme-health.com
|
|
117
144
|
```
|
|
118
145
|
|
|
119
146
|
### `validate`
|
|
120
147
|
|
|
121
148
|
Checks that the config shape is valid and that credentials are available.
|
|
122
149
|
By default this also calls the hosted Nexalink config-validation endpoint, which
|
|
123
|
-
confirms the API base URL,
|
|
124
|
-
|
|
150
|
+
confirms the API base URL, public embed key, payer ID, environment, and allowed
|
|
151
|
+
origins are accepted by the server. The browser-side validation request uses
|
|
152
|
+
public embed headers; it does not send the secret API key. Use `--local-only`
|
|
153
|
+
for schema-only checks.
|
|
125
154
|
|
|
126
155
|
```bash
|
|
127
156
|
npx @nexalink/carecompass-sdk validate --config carecompass/carecompass.config.json
|
|
@@ -149,6 +178,11 @@ npx @nexalink/carecompass-sdk doctor --config carecompass/carecompass.config.jso
|
|
|
149
178
|
|
|
150
179
|
`carecompass/carecompass.config.json` is safe to commit when it only contains public embed configuration. Do not add the secret API key to this file.
|
|
151
180
|
|
|
181
|
+
The config is client-facing by design. It should contain the public `embedKey`,
|
|
182
|
+
the payer ID, environment, allowed origins, branding, labels, theme, and prompt
|
|
183
|
+
settings. Store the secret API key only in the local CLI credentials file or an
|
|
184
|
+
approved server-side secret store.
|
|
185
|
+
|
|
152
186
|
```json
|
|
153
187
|
{
|
|
154
188
|
"payerId": "acme-health",
|
|
@@ -187,6 +221,24 @@ npx @nexalink/carecompass-sdk doctor --config carecompass/carecompass.config.jso
|
|
|
187
221
|
}
|
|
188
222
|
```
|
|
189
223
|
|
|
224
|
+
## Privacy-Safe Telemetry
|
|
225
|
+
|
|
226
|
+
Telemetry is enabled automatically with Nexalink-managed defaults. Integrators
|
|
227
|
+
do not need to run an additional CLI command, add a runtime config block, or
|
|
228
|
+
manage a PostHog token. The CLI also sends anonymous onboarding funnel events
|
|
229
|
+
using an ephemeral per-process session ID that is never persisted.
|
|
230
|
+
|
|
231
|
+
The SDK sends only allowlisted anonymous deployment-health events directly to
|
|
232
|
+
PostHog's public ingestion API. It does not bundle `posthog-js`, enable session
|
|
233
|
+
replay or autocapture, identify users, set cookies, or persist analytics state.
|
|
234
|
+
Prompts, model responses, chat history, user context, PHI/PII, credentials, raw
|
|
235
|
+
errors, and stack traces are never included. CLI arguments, terminal input, and
|
|
236
|
+
file paths are also excluded.
|
|
237
|
+
|
|
238
|
+
The SDK uses a Nexalink-owned public PostHog ingestion token. See
|
|
239
|
+
[`TELEMETRY.md`](./TELEMETRY.md) for the shared web, React Native, and Flutter
|
|
240
|
+
event contract.
|
|
241
|
+
|
|
190
242
|
## System Prompt File
|
|
191
243
|
|
|
192
244
|
`carecompass/system-prompt.md` lets the payer define approved context before a member message reaches the LLM. Use it to steer CareCompass toward plan-specific terminology, support boundaries, escalation rules, and benefit-navigation context.
|
|
@@ -195,7 +247,7 @@ The prompt file is resolved by the CLI when it generates `carecompass/carecompas
|
|
|
195
247
|
|
|
196
248
|
## Iframe Placement
|
|
197
249
|
|
|
198
|
-
`carecompass/carecompass-iframe.html` contains the iframe to place on the
|
|
250
|
+
`carecompass/carecompass-iframe.html` contains the iframe to place on the integrating page where the CareCompass LLM should appear.
|
|
199
251
|
|
|
200
252
|
```html
|
|
201
253
|
<iframe
|
|
@@ -206,7 +258,7 @@ The prompt file is resolved by the CLI when it generates `carecompass/carecompas
|
|
|
206
258
|
></iframe>
|
|
207
259
|
```
|
|
208
260
|
|
|
209
|
-
Serve `carecompass/carecompass-embed.html` from the
|
|
261
|
+
Serve `carecompass/carecompass-embed.html` from the integrating site at the iframe `src`. For many apps, that means copying the generated `carecompass` folder into the app's public/static assets folder before deployment.
|
|
210
262
|
|
|
211
263
|
## React Usage
|
|
212
264
|
|
|
@@ -265,16 +317,31 @@ Peer dependency range:
|
|
|
265
317
|
|
|
266
318
|
The CLI requires Node.js 18 or newer.
|
|
267
319
|
|
|
320
|
+
## Development
|
|
321
|
+
|
|
322
|
+
This repository uses Bun for local development.
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
bun install
|
|
326
|
+
bun run build
|
|
327
|
+
bun run test
|
|
328
|
+
bun run pack:dry-run
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Do not publish a new package version unless the SDK version is intentionally
|
|
332
|
+
changed and release approval is complete.
|
|
333
|
+
|
|
268
334
|
## What Runs In The Browser
|
|
269
335
|
|
|
270
336
|
The browser receives only public embed configuration:
|
|
271
337
|
|
|
272
|
-
- payer ID
|
|
338
|
+
- customer or payer ID
|
|
273
339
|
- environment
|
|
274
340
|
- public `embedKey`
|
|
275
341
|
- branding and theme values
|
|
276
342
|
- labels and support links
|
|
277
343
|
- approved prompt settings
|
|
344
|
+
- Nexalink-managed telemetry defaults compiled into the SDK
|
|
278
345
|
|
|
279
346
|
The browser does not receive:
|
|
280
347
|
|
|
@@ -286,9 +353,46 @@ The browser does not receive:
|
|
|
286
353
|
|
|
287
354
|
Chat requests are sent to Nexalink-hosted CareCompass API routes. The component does not call the model endpoint directly.
|
|
288
355
|
|
|
356
|
+
## Hosted LLM Warm-Up
|
|
357
|
+
|
|
358
|
+
Nexalink hosts the proprietary CareCompass LLM runtime behind Nexalink-managed
|
|
359
|
+
API routes. To control infrastructure costs for early deployments, Nexalink may
|
|
360
|
+
run some hosted model endpoints with scale-to-zero capacity. When an endpoint
|
|
361
|
+
has scaled to zero, the first chat request after an idle period can take several
|
|
362
|
+
minutes while cloud GPU capacity is allocated and the model endpoint warms up.
|
|
363
|
+
|
|
364
|
+
This warm-up delay is expected for some MVP and development environments. It
|
|
365
|
+
does not mean the browser embed needs a secret API key, and it does not mean the
|
|
366
|
+
SDK is calling SageMaker directly. The request is queued through Nexalink-hosted
|
|
367
|
+
APIs while the model endpoint starts. Nexalink is actively working on
|
|
368
|
+
improvements to reduce or avoid first-request warm-up delays.
|
|
369
|
+
|
|
370
|
+
## Runtime Security Model
|
|
371
|
+
|
|
372
|
+
The SDK component uses the public browser `embedKey`, payer ID, environment, and
|
|
373
|
+
allowed origin metadata to call Nexalink-hosted embed API routes. The secret SDK
|
|
374
|
+
API key is used only by trusted setup and server-side/CLI workflows and must
|
|
375
|
+
never be placed in browser config or generated snippets.
|
|
376
|
+
|
|
377
|
+
For staging and production, `apiBaseUrl` must be a Nexalink-hosted HTTPS URL.
|
|
378
|
+
`localhost` API and origin values are accepted only for `development`
|
|
379
|
+
configurations. Hosted validation still remains authoritative: Nexalink API
|
|
380
|
+
routes must enforce payer ID, embed key, environment, allowed origin, prompt
|
|
381
|
+
guardrails, rate limiting, request attribution, and tenant isolation for config,
|
|
382
|
+
analytics, logs, prompts, and model requests.
|
|
383
|
+
|
|
384
|
+
Generated snippets escape serialized config before embedding it in a module
|
|
385
|
+
script. React renders chat messages and labels as text rather than raw HTML.
|
|
386
|
+
Do not add `dangerouslySetInnerHTML`, raw HTML snippets, unreviewed third-party
|
|
387
|
+
scripts, or payer-provided secret values to an embed page.
|
|
388
|
+
|
|
289
389
|
## API Keys And Usage Tracking
|
|
290
390
|
|
|
291
|
-
SDK API keys are issued in the
|
|
391
|
+
SDK API keys are issued in the Nexalink portal and stored server-side as hashes.
|
|
392
|
+
Each secret API key is associated with a customer or payer ID, environment,
|
|
393
|
+
public embed key, and allowed origins. The API key authenticates trusted setup
|
|
394
|
+
and management flows; the public embed key is what the browser uses for
|
|
395
|
+
client-facing runtime requests.
|
|
292
396
|
|
|
293
397
|
CareCompass usage under a key is tracked so Nexalink can support future Stripe metered billing. The backend records prompt tokens, completion tokens, total tokens, and last-used timestamps per payer/API key. Hosted routes use MedGemma token counts when they are available and fall back to estimates only when needed.
|
|
294
398
|
|
|
@@ -306,15 +410,22 @@ Before production, confirm:
|
|
|
306
410
|
|
|
307
411
|
- production origin is allowlisted exactly
|
|
308
412
|
- production `embedKey` is separate from staging
|
|
413
|
+
- production `apiBaseUrl` points at the approved Nexalink-hosted environment
|
|
309
414
|
- support links route to the payer's approved support surface
|
|
310
415
|
- prompt instructions are approved by Nexalink and the payer
|
|
311
416
|
- no secret API key appears in generated source code
|
|
417
|
+
- diagnostics, logs, and analytics are configured to avoid raw PHI/PII, raw
|
|
418
|
+
prompts, raw model responses, credentials, or privileged backend tokens unless
|
|
419
|
+
Nexalink has approved a secure diagnostic path
|
|
312
420
|
|
|
313
421
|
## Troubleshooting
|
|
314
422
|
|
|
315
423
|
`Missing Nexalink API key`
|
|
316
424
|
|
|
317
|
-
Run `npx @nexalink/carecompass-sdk
|
|
425
|
+
Run `npx @nexalink/carecompass-sdk init`, choose Developer, and sign in with an
|
|
426
|
+
API key. For non-interactive setup, pass `--account-type developer` with
|
|
427
|
+
`--api-key <key>`, or set `CARECOMPASS_API_KEY` with
|
|
428
|
+
`CARECOMPASS_ACCOUNT_TYPE=developer`.
|
|
318
429
|
|
|
319
430
|
`zsh: command not found: carecompass`
|
|
320
431
|
|
|
@@ -340,7 +451,7 @@ typing into the embed.
|
|
|
340
451
|
|
|
341
452
|
`Origin is not authorized`
|
|
342
453
|
|
|
343
|
-
Add the exact website origin to the
|
|
454
|
+
Add the exact website origin to the Nexalink portal SDK configuration.
|
|
344
455
|
|
|
345
456
|
`Prompt configuration violates CareCompass guardrails`
|
|
346
457
|
|
|
@@ -348,7 +459,7 @@ Remove unsafe or unsupported instructions and re-run validation.
|
|
|
348
459
|
|
|
349
460
|
`CareCompass embed client is not authorized`
|
|
350
461
|
|
|
351
|
-
Confirm `payerId`, `embedKey`, `environment`, and allowed origins match the key issued in the
|
|
462
|
+
Confirm `payerId`, `embedKey`, `environment`, and allowed origins match the key issued in the Nexalink portal.
|
|
352
463
|
|
|
353
464
|
`CareCompass AppSync inference service is not configured`
|
|
354
465
|
|
package/RELEASE.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# CareCompass SDK Release Process
|
|
2
|
+
|
|
3
|
+
This package is public, but production use requires Nexalink onboarding, BAA coverage where PHI may be involved, and Nexalink-issued credentials. Treat each package release as a supply-chain event.
|
|
4
|
+
|
|
5
|
+
## Release Authority
|
|
6
|
+
|
|
7
|
+
- Only approved Nexalink maintainers may publish `@nexalink/carecompass-sdk`.
|
|
8
|
+
- Publish from the canonical GitHub repository: `https://github.com/nexalink-care/carecompass-sdk`.
|
|
9
|
+
- Use the pinned package manager in `package.json` and keep `bun.lock` committed.
|
|
10
|
+
- Do not publish from a dirty working tree or from a local branch that has not passed review.
|
|
11
|
+
|
|
12
|
+
## Versioning
|
|
13
|
+
|
|
14
|
+
- Version and changelog updates are managed by release-please on `main`.
|
|
15
|
+
- Use beta versions for pre-production SDKs and avoid reusing a published version.
|
|
16
|
+
- Record security-relevant dependency or packaging changes in the release notes.
|
|
17
|
+
- Use conventional commit messages so release-please can classify release notes.
|
|
18
|
+
|
|
19
|
+
## Required Validation
|
|
20
|
+
|
|
21
|
+
Run the full local release check before publishing:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun install --frozen-lockfile
|
|
25
|
+
bun run release:check
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`release:check` runs lint, tests, build, dependency audit, and a dry-run package assembly. The package dry run uses `bun pm pack --dry-run --ignore-scripts` so package assembly does not execute install lifecycle scripts.
|
|
29
|
+
|
|
30
|
+
Before approval, review the dry-run file list and confirm it contains only:
|
|
31
|
+
|
|
32
|
+
- `dist/**/*.js`
|
|
33
|
+
- `dist/**/*.d.ts`
|
|
34
|
+
- `CHANGELOG.md`
|
|
35
|
+
- `README.md`
|
|
36
|
+
- `TELEMETRY.md`
|
|
37
|
+
- `LICENSE`
|
|
38
|
+
- `RELEASE.md`
|
|
39
|
+
- `SECURITY_AUDIT.md`
|
|
40
|
+
- `RUNTIME_SECURITY_AUDIT.md`
|
|
41
|
+
- `package.json`
|
|
42
|
+
|
|
43
|
+
Do not publish source maps, local credentials, generated payer configs, test fixtures with secret-like values, `.env` files, package-manager caches, or build logs.
|
|
44
|
+
|
|
45
|
+
## Dependency And Lockfile Controls
|
|
46
|
+
|
|
47
|
+
- Use `bun install --frozen-lockfile` in CI to verify reproducible installs.
|
|
48
|
+
- Run `bun audit` before every release.
|
|
49
|
+
- Review `bun outdated` output during routine maintenance and update dev tooling deliberately.
|
|
50
|
+
- Do not add install lifecycle scripts unless the security impact is documented and reviewed.
|
|
51
|
+
- Do not trust transitive package lifecycle scripts in Bun unless there is a specific approved need.
|
|
52
|
+
|
|
53
|
+
## Provenance, SBOM, And Publishing
|
|
54
|
+
|
|
55
|
+
Preferred production publishing should use npm trusted publishing or `npm publish --provenance --access public` from CI after the release check passes. Local publishing is allowed only for emergency releases approved by the package owners.
|
|
56
|
+
|
|
57
|
+
Generate an SBOM during CI when the release pipeline supports it, and retain the SBOM, audit output, package dry-run output, and final tarball integrity in release artifacts.
|
|
58
|
+
|
|
59
|
+
Release PRs are opened by `.github/workflows/release-please.yml` using the manifest files under `.github/`. Merging the release PR updates `package.json`, `CHANGELOG.md`, and the release manifest, then creates the GitHub release.
|
|
60
|
+
|
|
61
|
+
## Secret Handling
|
|
62
|
+
|
|
63
|
+
- Never place Nexalink SDK API keys, payer credentials, SageMaker credentials, AppSync signing roles, or private endpoint URLs in source, docs, tests, generated snippets, package metadata, or release artifacts.
|
|
64
|
+
- CLI credentials must stay in the local credentials file or environment variables described in `README.md`.
|
|
65
|
+
- Generated browser embed files may include public payer configuration and prompt text. Review generated files before committing them to an integrating application.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# CARE-153 Runtime, API, And Tenant-Isolation Audit
|
|
2
|
+
|
|
3
|
+
Audit date: 2026-05-30
|
|
4
|
+
|
|
5
|
+
Scope: SDK-side runtime, embed, CLI validation, generated snippets, browser configuration, prompt configuration, sensitive-data handling, and documentation for payer deployments. Hosted Nexalink API route implementations, backend rate limiting, backend CORS enforcement, backend logs, analytics stores, and SageMaker/AppSync infrastructure are outside this repository and must be validated in the hosted API codebase.
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
|
|
9
|
+
The SDK does not ship private SageMaker credentials, AppSync signing roles, privileged backend tokens, or secret Nexalink SDK API keys to the browser. Browser requests use public payer configuration and public embed headers; backend hosted routes remain the authoritative enforcement point for payer identity, embed-key authorization, allowed origins, rate limits, prompt guardrails, logs, analytics, and tenant isolation.
|
|
10
|
+
|
|
11
|
+
This audit found and remediated two SDK-side runtime issues:
|
|
12
|
+
|
|
13
|
+
- Staging and production configs could previously point `apiBaseUrl` at any HTTPS origin. The schema now requires a Nexalink-hosted HTTPS API URL for staging and production, with localhost allowed only for development.
|
|
14
|
+
- Generated embed snippets previously serialized config with plain `JSON.stringify` inside a module script. Config values containing `</script>` could break the script context when served as raw HTML. Snippet generation now escapes script-sensitive JSON characters and iframe attributes.
|
|
15
|
+
|
|
16
|
+
## Auth And API Access Model
|
|
17
|
+
|
|
18
|
+
- CLI commands use the secret Nexalink SDK API key from `--api-key`, `CARECOMPASS_API_KEY`, or the local credentials file.
|
|
19
|
+
- `init` uses that API key to check BAA status and submit execution metadata to Nexalink-hosted routes. The CLI never receives AWS credentials.
|
|
20
|
+
- Browser/runtime code never receives the secret SDK API key.
|
|
21
|
+
- Browser requests include:
|
|
22
|
+
- `x-carecompass-payer-id`
|
|
23
|
+
- `x-carecompass-embed-key`
|
|
24
|
+
- `x-carecompass-environment`
|
|
25
|
+
- Browser requests target only these SDK paths under the configured Nexalink-hosted API base URL:
|
|
26
|
+
- `POST /api/carecompass/embed/config/validate`
|
|
27
|
+
- `POST /api/carecompass/embed/ask`
|
|
28
|
+
- `GET /api/carecompass/embed/status/:jobId`
|
|
29
|
+
|
|
30
|
+
Backend requirements that must remain enforced outside this SDK:
|
|
31
|
+
|
|
32
|
+
- payer ID and embed key binding
|
|
33
|
+
- environment binding
|
|
34
|
+
- exact allowed-origin checks
|
|
35
|
+
- tenant isolation for configuration, prompts, requests, responses, logs, analytics, and usage records
|
|
36
|
+
- rate limiting and request attribution by payer/deployment
|
|
37
|
+
|
|
38
|
+
## Tenant Isolation Review
|
|
39
|
+
|
|
40
|
+
SDK-side controls:
|
|
41
|
+
|
|
42
|
+
- The config schema validates payer ID format, embed key format, deployment environment, allowed origins, API base URL, prompt structure, theme values, and public branding fields.
|
|
43
|
+
- Staging and production cannot use localhost API base URLs or localhost allowed origins.
|
|
44
|
+
- The client sends payer ID, embed key, and environment on every config-validation and inference request.
|
|
45
|
+
- The SDK does not expose APIs for reading another payer's configuration, analytics, logs, prompt history, or user data.
|
|
46
|
+
|
|
47
|
+
Backend-owned validation:
|
|
48
|
+
|
|
49
|
+
- The SDK cannot prove cross-payer isolation by itself because tenant state lives in hosted Nexalink services.
|
|
50
|
+
- Hosted routes must reject mismatched payer ID, embed key, environment, and origin tuples.
|
|
51
|
+
- Hosted routes must scope job status lookups by payer/deployment, not only by `jobId`.
|
|
52
|
+
|
|
53
|
+
## Allowed Origin And API Base URL Controls
|
|
54
|
+
|
|
55
|
+
Resolved in this branch:
|
|
56
|
+
|
|
57
|
+
- `apiBaseUrl` must be a Nexalink-hosted HTTPS URL, except localhost for development.
|
|
58
|
+
- Staging and production configs reject localhost `apiBaseUrl`.
|
|
59
|
+
- Staging and production configs reject localhost allowed origins.
|
|
60
|
+
- Browser-hosted pages still fail fast if a non-local page tries to call a localhost API base URL.
|
|
61
|
+
|
|
62
|
+
Follow-up for hosted API:
|
|
63
|
+
|
|
64
|
+
- Test unauthorized origins against deployed staging and production routes.
|
|
65
|
+
- Confirm CORS and origin checks happen server-side and are not based only on SDK validation.
|
|
66
|
+
|
|
67
|
+
## Client-Side Token And Secret Handling
|
|
68
|
+
|
|
69
|
+
No client-side secret exposure was found.
|
|
70
|
+
|
|
71
|
+
- Secret SDK API keys are read by the CLI only.
|
|
72
|
+
- The browser receives public `embedKey`, payer ID, environment, branding, labels, allowed origins, and prompt configuration.
|
|
73
|
+
- Credential storage writes local keys with file mode `0600`.
|
|
74
|
+
- CLI output prints the credentials path and source, not the API key value.
|
|
75
|
+
- Executed BAA copies contain agreement metadata and terms, not the SDK API key
|
|
76
|
+
or private cloud credentials. The CLI writes local executed copies with
|
|
77
|
+
owner-only (`0600`) permissions.
|
|
78
|
+
|
|
79
|
+
## Prompt Controls And Sensitive Data Handling
|
|
80
|
+
|
|
81
|
+
SDK-side controls:
|
|
82
|
+
|
|
83
|
+
- Prompt instructions are length-limited and checked for explicit guardrail-bypass patterns.
|
|
84
|
+
- Generated setup guidance warns against secrets, raw PHI, diagnosis instructions, treatment instructions, and guardrail bypass attempts in prompt files.
|
|
85
|
+
- `allowUserContext` defaults to `false`.
|
|
86
|
+
|
|
87
|
+
Backend-owned validation:
|
|
88
|
+
|
|
89
|
+
- Hosted routes must re-validate prompt configuration against Nexalink policy because browser config is attacker-controlled.
|
|
90
|
+
- Hosted routes must treat user messages, prompt content, model responses, and optional user context as sensitive data.
|
|
91
|
+
|
|
92
|
+
## Embed, XSS, And CSP Review
|
|
93
|
+
|
|
94
|
+
Resolved in this branch:
|
|
95
|
+
|
|
96
|
+
- Generated config JSON is escaped before insertion into `<script type="module">`.
|
|
97
|
+
- Generated iframe `title` and `src` attributes are HTML-attribute escaped.
|
|
98
|
+
|
|
99
|
+
Existing controls:
|
|
100
|
+
|
|
101
|
+
- React renders labels and messages as text, not raw HTML.
|
|
102
|
+
- The component does not use `dangerouslySetInnerHTML`, `innerHTML`, `eval`, or `new Function`.
|
|
103
|
+
|
|
104
|
+
Integration guidance:
|
|
105
|
+
|
|
106
|
+
- Prefer bundler mode over CDN mode for production.
|
|
107
|
+
- If CDN mode is used for a raw browser demo, the integrating page should set CSP `script-src` for the approved CDN and Nexalink assets only.
|
|
108
|
+
- Do not place unreviewed payer-provided HTML or third-party scripts in generated embed pages.
|
|
109
|
+
|
|
110
|
+
## Logging, Diagnostics, Telemetry, And Errors
|
|
111
|
+
|
|
112
|
+
CARE-158 adds an always-on privacy-safe telemetry transport documented in
|
|
113
|
+
`TELEMETRY.md`. The SDK sends only allowlisted anonymous lifecycle metadata to
|
|
114
|
+
PostHog's public ingestion API using a Nexalink-owned public ingestion token.
|
|
115
|
+
Integrators do not configure telemetry or receive a disable switch. The SDK
|
|
116
|
+
does not bundle `posthog-js`, enable session replay or autocapture, identify
|
|
117
|
+
users, set cookies, or persist analytics state.
|
|
118
|
+
|
|
119
|
+
The CLI sends fixed onboarding funnel events through the same transport. Each
|
|
120
|
+
CLI process uses an ephemeral random session ID that is not persisted. CLI
|
|
121
|
+
payloads exclude arguments, terminal input, file paths, API keys, and BAA signer
|
|
122
|
+
details.
|
|
123
|
+
|
|
124
|
+
Telemetry payloads exclude prompts, model responses, chat history, optional
|
|
125
|
+
user context, PHI/PII, credentials, raw errors, stack traces, request payloads,
|
|
126
|
+
and response bodies. Error telemetry uses fixed codes and categories. Telemetry
|
|
127
|
+
delivery failures are swallowed so analytics cannot interrupt SDK workflows.
|
|
128
|
+
Runtime errors shown in the component remain derived from local network
|
|
129
|
+
failures or backend error responses.
|
|
130
|
+
|
|
131
|
+
Backend-owned controls:
|
|
132
|
+
|
|
133
|
+
- Hosted routes must avoid logging raw PHI/PII, credentials, raw prompts, raw model responses, or privileged backend tokens unless an explicitly approved secure diagnostic path exists.
|
|
134
|
+
- Backend error responses should be sanitized because the component may display the error message.
|
|
135
|
+
|
|
136
|
+
## Rate Limiting And Abuse Prevention
|
|
137
|
+
|
|
138
|
+
The SDK can attribute requests by payer ID, embed key, and environment headers, but cannot enforce real rate limits or abuse controls because browser clients are untrusted.
|
|
139
|
+
|
|
140
|
+
Hosted routes must enforce:
|
|
141
|
+
|
|
142
|
+
- per-payer and per-origin rate limits
|
|
143
|
+
- per-embed-key request attribution
|
|
144
|
+
- abuse detection for prompt flooding and job-status polling
|
|
145
|
+
- safe status lookup scoping by payer/deployment
|
|
146
|
+
|
|
147
|
+
## Verification
|
|
148
|
+
|
|
149
|
+
Commands run:
|
|
150
|
+
|
|
151
|
+
| Command | Result |
|
|
152
|
+
| ----------------------- | ------------------------------------------------------------------------------------------- |
|
|
153
|
+
| `bun run test` | Validates schema hardening, snippet escaping, CLI behavior, and component runtime requests. |
|
|
154
|
+
| `bun run lint` | Ensures code quality after remediation. |
|
|
155
|
+
| `bun run build` | Regenerates distributable JavaScript and declarations. |
|
|
156
|
+
| `bun run release:check` | Runs frozen install, lint, tests, build, audit, and package dry run. |
|
|
157
|
+
|
|
158
|
+
New regression coverage:
|
|
159
|
+
|
|
160
|
+
- Reject non-Nexalink `apiBaseUrl` values.
|
|
161
|
+
- Allow localhost API/origin/support URLs only for development.
|
|
162
|
+
- Reject unsafe branding URL schemes.
|
|
163
|
+
- Escape `</script>`-style values in generated embed config JSON.
|
|
164
|
+
- Escape iframe attributes.
|
|
165
|
+
|
|
166
|
+
## Findings And Follow-Up
|
|
167
|
+
|
|
168
|
+
Resolved:
|
|
169
|
+
|
|
170
|
+
- Medium: staging/production `apiBaseUrl` allowed arbitrary HTTPS endpoints. Owner: SDK. Remediation: require Nexalink-hosted HTTPS API URLs outside development.
|
|
171
|
+
- Medium: generated script snippets did not escape script-sensitive JSON characters. Owner: SDK. Remediation: escape `<`, `>`, `&`, U+2028, and U+2029 in serialized config JSON.
|
|
172
|
+
|
|
173
|
+
No high or critical SDK-side runtime findings remain in this repository.
|
|
174
|
+
|
|
175
|
+
Follow-up required outside this SDK repository:
|
|
176
|
+
|
|
177
|
+
- Validate deployed hosted API CORS/origin enforcement with unauthorized origins.
|
|
178
|
+
- Validate cross-payer tenant isolation for config, prompt, analytics, logs, job status, and model request data in the hosted API codebase.
|
|
179
|
+
- Validate backend log/telemetry redaction for raw prompts, model responses, credentials, PHI/PII, and privileged tokens.
|
|
180
|
+
- Validate backend rate limiting and request attribution by payer, environment, origin, and embed key.
|