@choiceapps/communityservices-sdk 0.1.0
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/AGENTS.md +43 -0
- package/API.md +86 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE +201 -0
- package/NOTICE +11 -0
- package/README.md +100 -0
- package/SSVF.md +131 -0
- package/browser/attachment-conflict.mjs +6 -0
- package/browser/case-plans-ui.mjs +23 -0
- package/browser/case-plans.d.mts +20 -0
- package/browser/case-plans.mjs +89 -0
- package/browser/client-creation.d.mts +16 -0
- package/browser/client-creation.mjs +60 -0
- package/browser/client-profile-ui.mjs +59 -0
- package/browser/client-profile.d.mts +24 -0
- package/browser/client-profile.mjs +94 -0
- package/browser/client-workflows.mjs +135 -0
- package/browser/connection.d.mts +4 -0
- package/browser/connection.mjs +41 -0
- package/browser/current-living-situation.d.mts +44 -0
- package/browser/current-living-situation.mjs +161 -0
- package/browser/date-of-birth-ui.mjs +68 -0
- package/browser/date-of-birth.d.mts +28 -0
- package/browser/date-of-birth.mjs +112 -0
- package/browser/enrollment-workflow.d.mts +174 -0
- package/browser/enrollment-workflow.mjs +518 -0
- package/browser/exit-details.mjs +21 -0
- package/browser/file-store.mjs +32 -0
- package/browser/gwt-mapped.mjs +46 -0
- package/browser/household-exit.d.mts +34 -0
- package/browser/household-exit.mjs +102 -0
- package/browser/households-ui.mjs +20 -0
- package/browser/households.d.mts +22 -0
- package/browser/households.mjs +115 -0
- package/browser/index.d.mts +78 -0
- package/browser/index.mjs +46 -0
- package/browser/member-entry-date.d.mts +30 -0
- package/browser/member-entry-date.mjs +71 -0
- package/browser/need-recording.d.mts +37 -0
- package/browser/need-recording.mjs +68 -0
- package/browser/need-ui.mjs +138 -0
- package/browser/page-lock.mjs +11 -0
- package/browser/password-recovery.mjs +49 -0
- package/browser/playwright-session.mjs +196 -0
- package/browser/program-discovery.d.mts +22 -0
- package/browser/program-discovery.mjs +80 -0
- package/browser/recovery-diagnostics.mjs +9 -0
- package/browser/service-recording.d.mts +45 -0
- package/browser/service-recording.mjs +148 -0
- package/browser/service-ui.mjs +160 -0
- package/browser/session-authentication.mjs +40 -0
- package/browser/shelter-inventory.d.mts +103 -0
- package/browser/shelter-inventory.mjs +273 -0
- package/browser/shelter-ui.mjs +382 -0
- package/browser/shelters.d.mts +139 -0
- package/browser/shelters.mjs +425 -0
- package/browser/ssvf-rules.d.mts +21 -0
- package/browser/ssvf-rules.mjs +145 -0
- package/browser/ui-login.mjs +135 -0
- package/dist/cjs/bulk.d.ts +33 -0
- package/dist/cjs/bulk.d.ts.map +1 -0
- package/dist/cjs/bulk.js +42 -0
- package/dist/cjs/bulk.js.map +1 -0
- package/dist/cjs/control.d.ts +35 -0
- package/dist/cjs/control.d.ts.map +1 -0
- package/dist/cjs/control.js +141 -0
- package/dist/cjs/control.js.map +1 -0
- package/dist/cjs/effective-date.d.ts +3 -0
- package/dist/cjs/effective-date.d.ts.map +1 -0
- package/dist/cjs/effective-date.js +27 -0
- package/dist/cjs/effective-date.js.map +1 -0
- package/dist/cjs/encoding.d.ts +32 -0
- package/dist/cjs/encoding.d.ts.map +1 -0
- package/dist/cjs/encoding.js +121 -0
- package/dist/cjs/encoding.js.map +1 -0
- package/dist/cjs/enrollment-verifications.d.ts +39 -0
- package/dist/cjs/enrollment-verifications.d.ts.map +1 -0
- package/dist/cjs/enrollment-verifications.js +96 -0
- package/dist/cjs/enrollment-verifications.js.map +1 -0
- package/dist/cjs/errors.d.ts +33 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +45 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/generated/v2-models.d.ts +1482 -0
- package/dist/cjs/generated/v2-models.d.ts.map +1 -0
- package/dist/cjs/generated/v2-models.js +3 -0
- package/dist/cjs/generated/v2-models.js.map +1 -0
- package/dist/cjs/generated/v2.d.ts +1149 -0
- package/dist/cjs/generated/v2.d.ts.map +1 -0
- package/dist/cjs/generated/v2.js +252 -0
- package/dist/cjs/generated/v2.js.map +1 -0
- package/dist/cjs/generated/v3-models.d.ts +1420 -0
- package/dist/cjs/generated/v3-models.d.ts.map +1 -0
- package/dist/cjs/generated/v3-models.js +3 -0
- package/dist/cjs/generated/v3-models.js.map +1 -0
- package/dist/cjs/generated/v3.d.ts +1149 -0
- package/dist/cjs/generated/v3.d.ts.map +1 -0
- package/dist/cjs/generated/v3.js +252 -0
- package/dist/cjs/generated/v3.js.map +1 -0
- package/dist/cjs/gwt-enrollments.d.ts +131 -0
- package/dist/cjs/gwt-enrollments.d.ts.map +1 -0
- package/dist/cjs/gwt-enrollments.js +280 -0
- package/dist/cjs/gwt-enrollments.js.map +1 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/metadata.d.ts +100 -0
- package/dist/cjs/metadata.d.ts.map +1 -0
- package/dist/cjs/metadata.js +165 -0
- package/dist/cjs/metadata.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/program-discovery.d.ts +28 -0
- package/dist/cjs/program-discovery.d.ts.map +1 -0
- package/dist/cjs/program-discovery.js +58 -0
- package/dist/cjs/program-discovery.js.map +1 -0
- package/dist/cjs/race.d.ts +4 -0
- package/dist/cjs/race.d.ts.map +1 -0
- package/dist/cjs/race.js +40 -0
- package/dist/cjs/race.js.map +1 -0
- package/dist/cjs/runtime.d.ts +108 -0
- package/dist/cjs/runtime.d.ts.map +1 -0
- package/dist/cjs/runtime.js +38 -0
- package/dist/cjs/runtime.js.map +1 -0
- package/dist/cjs/subassessments.d.ts +29 -0
- package/dist/cjs/subassessments.d.ts.map +1 -0
- package/dist/cjs/subassessments.js +107 -0
- package/dist/cjs/subassessments.js.map +1 -0
- package/dist/cjs/testing.d.ts +45 -0
- package/dist/cjs/testing.d.ts.map +1 -0
- package/dist/cjs/testing.js +66 -0
- package/dist/cjs/testing.js.map +1 -0
- package/dist/cjs/transport.d.ts +19 -0
- package/dist/cjs/transport.d.ts.map +1 -0
- package/dist/cjs/transport.js +373 -0
- package/dist/cjs/transport.js.map +1 -0
- package/dist/cjs/v2.d.ts +13 -0
- package/dist/cjs/v2.d.ts.map +1 -0
- package/dist/cjs/v2.js +29 -0
- package/dist/cjs/v2.js.map +1 -0
- package/dist/cjs/v3.d.ts +13 -0
- package/dist/cjs/v3.d.ts.map +1 -0
- package/dist/cjs/v3.js +29 -0
- package/dist/cjs/v3.js.map +1 -0
- package/dist/cjs/validation.d.ts +33 -0
- package/dist/cjs/validation.d.ts.map +1 -0
- package/dist/cjs/validation.js +77 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/cjs/verification.d.ts +82 -0
- package/dist/cjs/verification.d.ts.map +1 -0
- package/dist/cjs/verification.js +122 -0
- package/dist/cjs/verification.js.map +1 -0
- package/dist/esm/bulk.d.ts +33 -0
- package/dist/esm/bulk.d.ts.map +1 -0
- package/dist/esm/bulk.js +39 -0
- package/dist/esm/bulk.js.map +1 -0
- package/dist/esm/control.d.ts +35 -0
- package/dist/esm/control.d.ts.map +1 -0
- package/dist/esm/control.js +132 -0
- package/dist/esm/control.js.map +1 -0
- package/dist/esm/effective-date.d.ts +3 -0
- package/dist/esm/effective-date.d.ts.map +1 -0
- package/dist/esm/effective-date.js +24 -0
- package/dist/esm/effective-date.js.map +1 -0
- package/dist/esm/encoding.d.ts +32 -0
- package/dist/esm/encoding.d.ts.map +1 -0
- package/dist/esm/encoding.js +117 -0
- package/dist/esm/encoding.js.map +1 -0
- package/dist/esm/enrollment-verifications.d.ts +39 -0
- package/dist/esm/enrollment-verifications.d.ts.map +1 -0
- package/dist/esm/enrollment-verifications.js +93 -0
- package/dist/esm/enrollment-verifications.js.map +1 -0
- package/dist/esm/errors.d.ts +33 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +33 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/generated/v2-models.d.ts +1482 -0
- package/dist/esm/generated/v2-models.d.ts.map +1 -0
- package/dist/esm/generated/v2-models.js +2 -0
- package/dist/esm/generated/v2-models.js.map +1 -0
- package/dist/esm/generated/v2.d.ts +1149 -0
- package/dist/esm/generated/v2.d.ts.map +1 -0
- package/dist/esm/generated/v2.js +247 -0
- package/dist/esm/generated/v2.js.map +1 -0
- package/dist/esm/generated/v3-models.d.ts +1420 -0
- package/dist/esm/generated/v3-models.d.ts.map +1 -0
- package/dist/esm/generated/v3-models.js +2 -0
- package/dist/esm/generated/v3-models.js.map +1 -0
- package/dist/esm/generated/v3.d.ts +1149 -0
- package/dist/esm/generated/v3.d.ts.map +1 -0
- package/dist/esm/generated/v3.js +247 -0
- package/dist/esm/generated/v3.js.map +1 -0
- package/dist/esm/gwt-enrollments.d.ts +131 -0
- package/dist/esm/gwt-enrollments.d.ts.map +1 -0
- package/dist/esm/gwt-enrollments.js +274 -0
- package/dist/esm/gwt-enrollments.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/metadata.d.ts +100 -0
- package/dist/esm/metadata.d.ts.map +1 -0
- package/dist/esm/metadata.js +157 -0
- package/dist/esm/metadata.js.map +1 -0
- package/dist/esm/program-discovery.d.ts +28 -0
- package/dist/esm/program-discovery.d.ts.map +1 -0
- package/dist/esm/program-discovery.js +55 -0
- package/dist/esm/program-discovery.js.map +1 -0
- package/dist/esm/race.d.ts +4 -0
- package/dist/esm/race.d.ts.map +1 -0
- package/dist/esm/race.js +37 -0
- package/dist/esm/race.js.map +1 -0
- package/dist/esm/runtime.d.ts +108 -0
- package/dist/esm/runtime.d.ts.map +1 -0
- package/dist/esm/runtime.js +33 -0
- package/dist/esm/runtime.js.map +1 -0
- package/dist/esm/subassessments.d.ts +29 -0
- package/dist/esm/subassessments.d.ts.map +1 -0
- package/dist/esm/subassessments.js +103 -0
- package/dist/esm/subassessments.js.map +1 -0
- package/dist/esm/testing.d.ts +45 -0
- package/dist/esm/testing.d.ts.map +1 -0
- package/dist/esm/testing.js +60 -0
- package/dist/esm/testing.js.map +1 -0
- package/dist/esm/transport.d.ts +19 -0
- package/dist/esm/transport.d.ts.map +1 -0
- package/dist/esm/transport.js +369 -0
- package/dist/esm/transport.js.map +1 -0
- package/dist/esm/v2.d.ts +13 -0
- package/dist/esm/v2.d.ts.map +1 -0
- package/dist/esm/v2.js +13 -0
- package/dist/esm/v2.js.map +1 -0
- package/dist/esm/v3.d.ts +13 -0
- package/dist/esm/v3.d.ts.map +1 -0
- package/dist/esm/v3.js +13 -0
- package/dist/esm/v3.js.map +1 -0
- package/dist/esm/validation.d.ts +33 -0
- package/dist/esm/validation.d.ts.map +1 -0
- package/dist/esm/validation.js +72 -0
- package/dist/esm/validation.js.map +1 -0
- package/dist/esm/verification.d.ts +82 -0
- package/dist/esm/verification.d.ts.map +1 -0
- package/dist/esm/verification.js +117 -0
- package/dist/esm/verification.js.map +1 -0
- package/docs/README.md +56 -0
- package/docs/assessments.md +103 -0
- package/docs/browser-session.md +129 -0
- package/docs/capabilities.md +75 -0
- package/docs/configuration.md +81 -0
- package/docs/current-living-situation.md +56 -0
- package/docs/dates-and-answers.md +40 -0
- package/docs/development.md +81 -0
- package/docs/durable-records.md +156 -0
- package/docs/enrollments.md +217 -0
- package/docs/files-and-notes.md +39 -0
- package/docs/getting-started.md +56 -0
- package/docs/independent-needs.md +77 -0
- package/docs/integration-methods.md +60 -0
- package/docs/profiles.md +68 -0
- package/docs/reference.md +64 -0
- package/docs/rest-client.md +97 -0
- package/docs/services.md +66 -0
- package/docs/shelter-inventory.md +64 -0
- package/docs/shelters.md +75 -0
- package/docs/troubleshooting.md +61 -0
- package/docs/using-the-sdk.md +203 -0
- package/docs/vendor-issues/README.md +46 -0
- package/docs/vendor-issues/api-coverage.md +27 -0
- package/docs/vendor-issues/attachment-authentication.md +40 -0
- package/docs/vendor-issues/date-semantics.md +51 -0
- package/docs/vendor-issues/empty-service-list-404.md +51 -0
- package/docs/vendor-issues/enrollment-complete-target-error.md +178 -0
- package/docs/vendor-issues/enrollment-effective-date-column.md +112 -0
- package/docs/vendor-issues/household-head-validation.md +26 -0
- package/docs/vendor-issues/write-contracts.md +51 -0
- package/examples/README.md +41 -0
- package/examples/current-living-situation.mts +27 -0
- package/examples/durable-records.mts +78 -0
- package/examples/enrollment-workflow.mts +46 -0
- package/examples/gwt-enrollment-session.ts +17 -0
- package/examples/gwt-file-store.mjs +2 -0
- package/examples/household-enrollment-workflow.mts +43 -0
- package/examples/household-exit-workflow.mts +35 -0
- package/examples/household-lifecycle-workflow.mts +34 -0
- package/examples/independent-needs.mts +30 -0
- package/examples/program-discovery.ts +19 -0
- package/examples/quickstart.mjs +13 -0
- package/examples/shelter-inventory.mts +30 -0
- package/examples/shelters.mts +33 -0
- package/examples/usage.ts +23 -0
- package/examples/verification-snapshot.ts +9 -0
- package/llms.txt +26 -0
- package/package.json +103 -0
- package/specs/provenance.json +17 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Using the SDK
|
|
2
|
+
|
|
3
|
+
[Documentation index](README.md) · [Package overview](../README.md)
|
|
4
|
+
|
|
5
|
+
This guide takes an application from installation to its first REST read and browser session, then explains how to choose a workflow for writing records. Use Node 22 or newer. The SDK runs on your server; keep credentials and client records there.
|
|
6
|
+
|
|
7
|
+
## 1. Install the package
|
|
8
|
+
|
|
9
|
+
Install from the public npm registry. No registry token is required. For the private registry, follow [Install from GitLab](../README.md#install-from-gitlab).
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @choiceapps/communityservices-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For JavaScript, use `.mjs` files or set `"type": "module"` in your application's `package.json`. TypeScript applications can use `.mts` with `module` and `moduleResolution` set to `NodeNext`. REST imports also support CommonJS:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const {WellSkyClient, toItems} = require('@choiceapps/communityservices-sdk');
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The optional `/browser` export requires ESM. Install its dependency only when using browser workflows:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npm install playwright-core
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
It also needs an installed Chrome/Chromium executable. Set `HMIS_CHROME_PATH` to that executable, or install the matching Playwright browser using `npx playwright-core install chromium`.
|
|
28
|
+
|
|
29
|
+
## 2. Try an offline read
|
|
30
|
+
|
|
31
|
+
The installed package includes a runnable example with synthetic data:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
node node_modules/@choiceapps/communityservices-sdk/examples/quickstart.mjs
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Expected output:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
Read synthetic client 123; no network requests.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This runs the real SDK validation and transport through a fake that cannot contact WellSky. See the [offline quickstart](getting-started.md) for its source.
|
|
44
|
+
|
|
45
|
+
## 3. Configure your tenant and credentials
|
|
46
|
+
|
|
47
|
+
The application supplies the tenant. Every tenant uses the same SDK operations; no environment switch or separate helper names are needed. Tenant IDs, provider IDs, client IDs, and picklist choices must come from the deployment you are connecting to.
|
|
48
|
+
|
|
49
|
+
REST and browser credentials are separate. A registry token is only needed if you choose the private GitLab registry:
|
|
50
|
+
|
|
51
|
+
| Credential | Used for |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `GITLAB_NPM_TOKEN` | Downloading the package from GitLab |
|
|
54
|
+
| REST username/password, token, or token provider | Authenticating `WellSkyClient` API requests |
|
|
55
|
+
| `HMIS_UI_USER` and `HMIS_UI_PASSWORD` | Signing in to the web application through a browser helper |
|
|
56
|
+
|
|
57
|
+
For local development, create a private `.env.local` and exclude it from version control:
|
|
58
|
+
|
|
59
|
+
```dotenv
|
|
60
|
+
WELLSKY_TENANT=your-tenant
|
|
61
|
+
WELLSKY_USERNAME=your-rest-username
|
|
62
|
+
WELLSKY_PASSWORD=your-rest-password
|
|
63
|
+
WELLSKY_CLIENT_ID=replace-with-an-authorized-client-id
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
These `WELLSKY_*` names are conventions used by the example below. The REST client does not read the file or environment automatically. Node's `--env-file` option loads it, and your application passes the values to the SDK. Deployed applications can supply the same values through their secret manager.
|
|
67
|
+
|
|
68
|
+
## 4. Read an existing client
|
|
69
|
+
|
|
70
|
+
Save this complete example as `read-client.mjs`. It prints only the number of returned records; consume the client data inside your application.
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
import {WellSkyClient, WellSkyError, toItems} from '@choiceapps/communityservices-sdk';
|
|
74
|
+
|
|
75
|
+
const {WELLSKY_TENANT: tenant, WELLSKY_USERNAME: username,
|
|
76
|
+
WELLSKY_PASSWORD: password} = process.env;
|
|
77
|
+
const clientId = Number(process.env.WELLSKY_CLIENT_ID);
|
|
78
|
+
if (!tenant || !username || !password) throw new Error('Tenant and REST credentials are required');
|
|
79
|
+
if (!Number.isSafeInteger(clientId) || clientId < 1) throw new Error('A valid client ID is required');
|
|
80
|
+
|
|
81
|
+
const api = new WellSkyClient({
|
|
82
|
+
tenant,
|
|
83
|
+
auth: {kind: 'credentials', username, password},
|
|
84
|
+
timeoutMs: 30000,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const people = toItems(await api.clients.get({path: {clientId}}));
|
|
89
|
+
console.log(`Read ${people.length} client record(s).`);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (error instanceof WellSkyError) {
|
|
92
|
+
console.error({kind: error.kind, operation: error.operation, status: error.status});
|
|
93
|
+
} else {
|
|
94
|
+
console.error('The read could not be completed.');
|
|
95
|
+
}
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Run it with your configured client ID:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
node --env-file=.env.local read-client.mjs
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The root import uses V3. Import `WellSkyClient` from `@choiceapps/communityservices-sdk/v2` or `/v3` to choose explicitly. For a caller-managed token, replace `auth` with `{kind: 'token', token}`. For application-owned renewal, use `{kind: 'provider', getToken}`. See [REST configuration](rest-client.md) for those contracts.
|
|
107
|
+
|
|
108
|
+
Requests take a single object containing `path`, `query`, and/or `body`. Match the parameter spelling in the [API table](../API.md). `toItems()` normalizes supported collection response shapes; it does not turn HTTP errors into empty results. A 404 can indicate an upstream problem, so do not assume it means no record exists.
|
|
109
|
+
|
|
110
|
+
For large reads, use `api.paginate()` rather than treating one page as a complete result. For bounded groups of independent calls, use `api.bulk()`. Both are covered in [pagination and bulk calls](rest-client.md#bulk-execution-and-pagination).
|
|
111
|
+
|
|
112
|
+
## 5. Open a browser session when needed
|
|
113
|
+
|
|
114
|
+
Some operations depend on web application forms or GWT calls. The SDK manages a dedicated page for those operations. Browser login is separate from REST authentication.
|
|
115
|
+
|
|
116
|
+
Add the following to `.env.local`, using the same tenant as your REST client:
|
|
117
|
+
|
|
118
|
+
```dotenv
|
|
119
|
+
HMIS_UI_USER=your-browser-username
|
|
120
|
+
HMIS_UI_PASSWORD=your-browser-password
|
|
121
|
+
HMIS_CHROME_PATH=/absolute/path/to/chrome
|
|
122
|
+
WELLSKY_PROVIDER_ID=replace-with-an-authorized-provider-id
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Save this as `read-inventory.mjs`. It discovers the provider's shelter unit lists without creating a client record, need, service, or stay:
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
import {chromium} from 'playwright-core';
|
|
129
|
+
import {openUiSession, createShelterInventory} from '@choiceapps/communityservices-sdk/browser';
|
|
130
|
+
|
|
131
|
+
const tenant = process.env.WELLSKY_TENANT;
|
|
132
|
+
const executablePath = process.env.HMIS_CHROME_PATH;
|
|
133
|
+
const providerId = Number(process.env.WELLSKY_PROVIDER_ID);
|
|
134
|
+
if (!tenant) throw new Error('A tenant is required');
|
|
135
|
+
if (!Number.isSafeInteger(providerId) || providerId < 1) throw new Error('A valid provider ID is required');
|
|
136
|
+
|
|
137
|
+
const session = await openUiSession({
|
|
138
|
+
tenant,
|
|
139
|
+
chromium,
|
|
140
|
+
envFile: '.env.local',
|
|
141
|
+
...(executablePath ? {executablePath} : {}),
|
|
142
|
+
passwordRecovery: false,
|
|
143
|
+
});
|
|
144
|
+
try {
|
|
145
|
+
const inventory = createShelterInventory({page: session.page});
|
|
146
|
+
const catalog = await inventory.listUnitLists({providerId});
|
|
147
|
+
console.log(`Found ${catalog.unitLists.length} unit list(s).`);
|
|
148
|
+
} finally {
|
|
149
|
+
await session.close();
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
node --env-file=.env.local read-inventory.mjs
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Omit `HMIS_CHROME_PATH` when using Playwright's installed Chromium. The helper reads UI credentials from `envFile`; Node loads the application's tenant, executable path, and provider ID. By default the module URL is `https://wscs.wellsky.com/<tenant>/com.bowmansystems.sp5.core.ServicePoint/`. Supply `moduleBaseUrl` only when your deployment uses another HTTPS host; its tenant path must match.
|
|
158
|
+
|
|
159
|
+
This introductory example disables password recovery so it cannot change an expired password. The SDK's default recovery behavior can rotate an expired password and attempt to restore it. Review [password recovery](browser-session.md#expired-ui-passwords) before enabling it.
|
|
160
|
+
|
|
161
|
+
To read beds and availability, pass a discovered `unitListId` to `inventory.getInventory({providerId, unitListId})`; see the [inventory example](../examples/shelter-inventory.mts). Use the managed page exclusively for SDK helpers and always close the session in `finally`.
|
|
162
|
+
|
|
163
|
+
## 6. Choose a workflow for writes
|
|
164
|
+
|
|
165
|
+
Use the helper for the business operation you need. Raw REST calls expose the API; workflow helpers add discovery, validation, UI completion where needed, and durable reconciliation.
|
|
166
|
+
|
|
167
|
+
| Task | Start with | Guide |
|
|
168
|
+
| --- | --- | --- |
|
|
169
|
+
| Create a client and retain an external source identity | `createClientCreator` | [Durable records](durable-records.md) |
|
|
170
|
+
| Create or update household membership | `createHouseholds` | [Durable records](durable-records.md) |
|
|
171
|
+
| Enroll, review, or exit clients and households | `createEnrollmentWorkflow` | [Enrollments](enrollments.md) |
|
|
172
|
+
| Update profile fields or date of birth | `createClientProfile`, `createDateOfBirth` | [Profiles](profiles.md) |
|
|
173
|
+
| Record a service and complete its associated need | `createServiceRecorder` | [Services](services.md) |
|
|
174
|
+
| Record a need without a service | `createNeedRecorder` | [Independent needs](independent-needs.md) |
|
|
175
|
+
| Check into or out of shelter beds | `createShelters` | [Shelters](shelters.md) |
|
|
176
|
+
| Record outreach or shelter contacts | `createCurrentLivingSituationRecorder` | [Current Living Situation](current-living-situation.md) |
|
|
177
|
+
| Write notes, goals, action steps, or attachments | `createCasePlans`, `createClientWorkflows` | [Durable records](durable-records.md), [files and notes](files-and-notes.md) |
|
|
178
|
+
|
|
179
|
+
Before writing, discover the program's current assessment and picklist definitions and collect the application's intended answers. Do not copy numeric choice IDs or fixture values from another tenant. The [typed examples](../examples/README.md) show the dependencies and inputs required by each workflow; most export functions for your application to call rather than running on import.
|
|
180
|
+
|
|
181
|
+
Use `createFileGwtMutationStore('/persistent/private/sdk-journal')` for a single-host durable journal, or implement the store contract with shared locking for multiple hosts. Pass the same store to the cooperating helpers. `openEnrollmentSession({tenant, chromium, envFile, store})` returns the authenticated session together with enrollment helpers, an enrollment reader, and client workflows.
|
|
182
|
+
|
|
183
|
+
Use a stable upstream event ID as the operation's `key`, such as an intake record ID or contact event ID. Reuse that key, the original intent, and the same journal when resuming. Different real events need different keys even when dates and answers match. Persist returned record IDs and workflow results in your application. A temporary or in-memory journal cannot reconcile a process restart.
|
|
184
|
+
|
|
185
|
+
## 7. Handle failures without duplicating records
|
|
186
|
+
|
|
187
|
+
A successful HTTP response is not a guarantee that all fields saved. A failed response is not proof that nothing saved. Workflow helpers verify stored results and retain uncertain attempts in their journal.
|
|
188
|
+
|
|
189
|
+
- For validation or tenant mismatch errors, correct configuration or input before trying again.
|
|
190
|
+
- For an interrupted browser session, reauthenticate and reconcile the original operation. A fresh login does not clear its mutation history.
|
|
191
|
+
- For an ambiguous commit or conflict, inspect the workflow status and authoritative readback. Keep the original key and journal; do not wrap raw writes in a retry loop.
|
|
192
|
+
- For bulk work, persist fulfilled, rejected, and skipped outcomes. A failed progress callback does not undo a completed write.
|
|
193
|
+
|
|
194
|
+
Read [troubleshooting](troubleshooting.md) and the owning workflow's retry contract for the exact error and recovery path. Keep credentials and client data out of logs.
|
|
195
|
+
|
|
196
|
+
## Further reference
|
|
197
|
+
|
|
198
|
+
- [Configuration](configuration.md): connection options, authentication, timeouts, and concurrency.
|
|
199
|
+
- [Dates and answers](dates-and-answers.md): calendar dates, explicit instants, and metadata-driven choices.
|
|
200
|
+
- [Capabilities](capabilities.md): supported operations, observed limitations, and verification evidence reproduced in a sandbox tenant.
|
|
201
|
+
- [Development](development.md): working from source, synthetic tests, and packaging.
|
|
202
|
+
|
|
203
|
+
Sandbox reproductions establish the behavior observed in those fixtures. They do not establish permissions, configuration, or successful execution for every deployment. The API and helpers use the tenant supplied by your application.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Issues for WellSky support
|
|
2
|
+
|
|
3
|
+
[Documentation index](../README.md)
|
|
4
|
+
|
|
5
|
+
These reports describe observed Community Services Client API behavior. Reproductions use synthetic records in a sandbox tenant. They do not establish behavior in other tenant deployments. Credentials, client demographics, and raw authenticated browser payloads are excluded.
|
|
6
|
+
|
|
7
|
+
This is a feedback queue prepared for WellSky. It does not claim that these reports have been submitted, acknowledged, or fixed. The priorities below reflect integration impact. [Implementation rationale](../integration-methods.md) explains how each limitation affects the SDK's choice of REST, GWT-RPC, or browser operations.
|
|
8
|
+
|
|
9
|
+
## Reproduced failures to raise first
|
|
10
|
+
|
|
11
|
+
| Issue | Status | Impact |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Empty service collection returns HTTP 404](empty-service-list-404.md) | V3 reproduced October 24, 2026 | An existing client with zero services cannot be recognized as an empty collection from the REST status alone. |
|
|
14
|
+
| [Grouped enrollment reads report a missing database column](enrollment-effective-date-column.md) | V2 and V3 compared October 24, 2026 | All 16 tested grouped complete reads per version failed; individual enrollment pages in the same client could succeed. V2 is not a workaround. |
|
|
15
|
+
| [Missing DOB information triggers a complete-read target error](enrollment-complete-target-error.md) | V2 and V3 reproduced October 24, 2026 | DOB alone or unknown/declined DOB quality alone cleared the error in four synthetic fixtures; no birth date is needed for the tested quality responses. |
|
|
16
|
+
| [Service creation persists despite an HTTP 400](write-contracts.md#a-service-persisted-despite-http-400) | Reproduced October 24, 2026 | Retrying the failed create can duplicate a saved service. |
|
|
17
|
+
| [Omitted SSN is cleared by a client update](write-contracts.md#omitting-ssn-from-a-client-update-cleared-it) | Reproduced October 23, 2026; intended update semantics need clarification | A middle-name-only request cleared another field; the SDK preserves current fields before updating. |
|
|
18
|
+
| [Complete entry projection omits valid verification rows](date-semantics.md#complete-entry-projections-omit-valid-verification-rows) | V2 and V3 reproduced October 22, 2026, including a UI-created control | A complete response can omit rows valid at enrollment; changing the write method did not fix it. |
|
|
19
|
+
| [DOB correction fails at an existing effective timestamp](date-semantics.md#correcting-dob-at-an-existing-effective-timestamp-fails) | Reproduced October 23, 2026 | Changing the timestamp avoids the error by changing history; the SDK uses a limited matching-entry UI correction. |
|
|
20
|
+
| [Attachment authentication fails after a successful client read](attachment-authentication.md) | V2/V3 reads and native multipart create investigated October 22, 2026 | REST attachment operations remain unusable with the tested account; cause and additional permission requirements are unconfirmed. |
|
|
21
|
+
|
|
22
|
+
Prioritize write outcomes, omitted-field data preservation, and verification/date correctness because they can cause duplicate, cleared, or misinterpreted data. Attachment authentication and grouped reads block public-API-only integrations. Empty-collection responses complicate safe reconciliation.
|
|
23
|
+
|
|
24
|
+
For the grouped-enrollment issue, create an entry/exit shelter stay for a synthetic household through the UI, verify the resulting enrollment, then request its client enrollment list and complete enrollment. Expected: the existing enrollments and their details. Actual in the tested tenant: the SQL error above. This failure also occurred on previously created household enrollments; shelter creation is one reproduction path, not a proven cause.
|
|
25
|
+
|
|
26
|
+
The enrollment report includes a read-only reproduction using existing synthetic IDs, a V2/V3 result matrix, and pagination controls. The [separate target-error investigation](enrollment-complete-target-error.md) compares sparse enrollment 680 with three successful individual enrollments and compares DOB-only and quality-only answers through four controlled synthetic fixtures. The grouped report also records an empty enrollment-list HTTP 404 observed in both versions.
|
|
27
|
+
|
|
28
|
+
## Contract and response questions
|
|
29
|
+
|
|
30
|
+
- [Client update semantics](write-contracts.md#omitting-ssn-from-a-client-update-cleared-it): omitting SSN cleared its value. Clarify replacement versus partial-update behavior before classifying the omission rule as a defect.
|
|
31
|
+
- [Goal update and relationship contract](write-contracts.md#goal-updates-require-a-field-marked-optional): `clientId` was required despite an optional schema field; returned household rows did not match the inspected goal association.
|
|
32
|
+
- [Mobile effective dates](date-semantics.md#mobile-answer-writes-shift-the-effective-date) and [DOB serialization](date-semantics.md#dob-serialization-can-disagree-with-the-ui-calendar-date): document timezone/date-only rules and resolve inconsistent stored or displayed values. These are separate from complete-entry filtering.
|
|
33
|
+
- [Filtering, empty reads, and response shapes](write-contracts.md#filtering-and-response-shapes-vary-by-operation): document per-endpoint syntax and align responses with schemas.
|
|
34
|
+
- [Household head coverage](household-head-validation.md): the server accepted writes that left members enrolled after the original head exited. Clarify the intended validation and supported head-transfer/repair workflow; the SDK rejects that state.
|
|
35
|
+
|
|
36
|
+
## Missing public capabilities
|
|
37
|
+
|
|
38
|
+
[Public API coverage requests](api-coverage.md) covers program assessment assignments, grouped workflows, independent needs, SSVF periods, need outcomes, funding allocations, Sex, goal case notes, and shelter beds. These are capability requests or questions about an existing supported route, not automatically server bugs.
|
|
39
|
+
|
|
40
|
+
## Evidence to include with a report
|
|
41
|
+
|
|
42
|
+
Use the smallest authorized reproduction, with API version, endpoint, exact sanitized request fields, expected and observed behavior, and a successful control where available. Include request timestamps and correlation identifiers when available. Identify whether the same result was reproduced outside the SDK or through an ordinary UI save.
|
|
43
|
+
|
|
44
|
+
Keep suspected causes separate from observations. Do not send tokens, passwords, raw GWT payloads, or client records. Obtain any tenant-specific evidence through the authorized support channel. Do not rerun historical mutation scripts simply to regenerate evidence.
|
|
45
|
+
|
|
46
|
+
[Capabilities](../capabilities.md) records the current SDK limits and acceptance evidence. These reports preserve the useful observations, reproduction controls, implementation consequences, and questions for WellSky.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Public API coverage requests
|
|
2
|
+
|
|
3
|
+
[WellSky feedback](README.md) · [Why the SDK combines methods](../integration-methods.md)
|
|
4
|
+
|
|
5
|
+
These are requests for documented capabilities or confirmation of an existing supported route. Absence from the pinned V2/V3 Swagger and the inspected workflows is not proof that WellSky has no other API. The browser behaviors were reproduced in a sandbox tenant through October 24, 2026.
|
|
6
|
+
|
|
7
|
+
| Capability requested | Why the integration needs it | Current method |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Provider-to-assessment assignments and entry/interim/exit defaults | A provider catalog and client question list do not identify the correct program instrument | Provider Admin discovery and counted GWT reads |
|
|
10
|
+
| Linked household enrollment, selected-member reviews, and exits | Independent client enrollments do not preserve the UI's group relationships and selected-member semantics | Current UI models and GWT operations, followed by separate assessment writes |
|
|
11
|
+
| Independent need creation and service-type catalogs | Recording a need must not require inventing a service or referral | Add Need form, counted GWT taxonomy and program quicklist reads |
|
|
12
|
+
| SSVF assistance start/end dates | Service dates and the financial assistance period are different values | REST for supported fields, UI completion for the period |
|
|
13
|
+
| Need outcome and funding allocation writes | Service creation alone did not establish Fully Met or persist funding allocations through a documented REST field | Fresh service form completion and independent stored-allocation readback |
|
|
14
|
+
| Contextual Funding Source choices | Permitted funds depend on provider, service code, cycle, and session; an unscoped catalog is insufficient | Current UI query context with counted GWT reads |
|
|
15
|
+
| Client Record Sex | Updating the legacy REST Gender field did not populate Sex | Current Client Record form |
|
|
16
|
+
| Goal case-note reads and writes | Goal case notes differ from Client Notes and were not exposed in the tested REST goal response | Browser workflow and GWT reads |
|
|
17
|
+
| Named-bed assignment and shelter check-in/checkout | An ordinary shelter service does not reserve or assign a bed | Current shelter UI with enrollment and stay verification |
|
|
18
|
+
| Complete bed/unit inventory and availability | Aggregate provider inventory does not identify individual beds, occupants, holds, or current vacancies | Read-only browser inventory views |
|
|
19
|
+
| Readable conditional form rules and historical option semantics | Current question metadata does not fully describe conditional visibility, required fields, or past picklist values | Current form discovery and explicitly dated rule snapshots |
|
|
20
|
+
|
|
21
|
+
## Contract details needed for a REST replacement
|
|
22
|
+
|
|
23
|
+
For each operation, request supported authentication and permissions, exact request fields, stable record identities, counted pagination, and authoritative readback. Writes also need documented validation order, partial-commit behavior, and a way to reconcile a lost response without creating duplicates.
|
|
24
|
+
|
|
25
|
+
For grouped operations, ask whether the server commits the group atomically and how it reports member-level failures. For inventory, ask how a write checks availability at commit time; a prior availability read cannot reserve a bed.
|
|
26
|
+
|
|
27
|
+
Browser automation can be removed only after a supported alternative preserves the business operation and the SDK's recovery guarantees. Generic mapped-query access or a captured GWT request is not a substitute for a documented public contract.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Attachment authentication fails after successful ordinary API authentication
|
|
2
|
+
|
|
3
|
+
[WellSky feedback](README.md) · [SDK attachment handling](../files-and-notes.md)
|
|
4
|
+
|
|
5
|
+
Status: reproduced in a sandbox tenant on October 22, 2026. Attachment reads failed in V2 and V3. A native multipart create also failed. The root cause is unconfirmed; the evidence does not establish a failure for every account or tenant. This is prepared feedback, not a record of a submitted or acknowledged support ticket.
|
|
6
|
+
|
|
7
|
+
## Observed contract and result
|
|
8
|
+
|
|
9
|
+
The pinned attachment contracts require REST bearer authentication plus body credentials. `POST /fileattachments/clients/get` takes `username`, `password`, and `client_id`. `POST /fileattachments/clients/create` takes multipart credentials, entity metadata, and `fileData`.
|
|
10
|
+
|
|
11
|
+
| Control | Observed result |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Fresh `SetAuthKey` using the supplied REST account | HTTP 200 and a token |
|
|
14
|
+
| Ordinary client GET using that token | HTTP 200 and the expected synthetic client |
|
|
15
|
+
| Attachment list using the same token and credentials | HTTP 400: `User details are not matching with token user details` in both API versions |
|
|
16
|
+
| Native JSON list request outside the SDK | Same failure |
|
|
17
|
+
| Native Node FormData upload | Same mismatch; locally decoded multipart fields and bytes matched the intended values |
|
|
18
|
+
| Fresh authenticated browser attachment read after the failed upload | Existing attachment identities unchanged; attempted filename absent |
|
|
19
|
+
|
|
20
|
+
The username had no surrounding whitespace and matched the token's `unique_name`. The token's `user_id` contained literal single quotes around the numeric value, for example `"'1234'"`. That format is a possible contributor if the server compares quoted and unquoted identities. It is not a proven cause. Account permissions or another server lookup remain possible explanations.
|
|
21
|
+
|
|
22
|
+
Alternate documented authentication routes did not produce a working attachment token. No evidence justified password encoding changes, editing a signed token, or silently using another account.
|
|
23
|
+
|
|
24
|
+
## Reproduction for an authorized support session
|
|
25
|
+
|
|
26
|
+
1. Select a synthetic client and an account with confirmed intended attachment permissions.
|
|
27
|
+
2. Mint a fresh REST token and confirm an ordinary client GET succeeds.
|
|
28
|
+
3. Use the same token, tenant, and account in the documented attachment-list request for V3 and V2.
|
|
29
|
+
4. Compare the HTTP result and sanitized error with a native request outside the SDK.
|
|
30
|
+
|
|
31
|
+
The list request is enough to demonstrate the mismatch without uploading a file. Token minting can still affect other sessions. An upload reproduction requires separately authorized write scope.
|
|
32
|
+
|
|
33
|
+
## Questions for WellSky
|
|
34
|
+
|
|
35
|
+
- What account type, permissions, and token flow do these attachment routes require?
|
|
36
|
+
- Does attachment identity validation accept the single-quoted `user_id` issued by `SetAuthKey`?
|
|
37
|
+
- Are the additional body credentials expected to match the bearer-token account exactly?
|
|
38
|
+
- If additional requirements exist, can they be included in Swagger with a working request example?
|
|
39
|
+
|
|
40
|
+
The SDK currently uses browser-authenticated multipart uploads and verifies stored bytes by downloading and hashing them. No client-side REST serialization or authentication defect was established. Supply request timestamps, versions, paths, and correlation identifiers to support; keep passwords, bearer tokens, raw JWTs, and client data out of shared reports.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Date handling and enrollment projections need separate fixes
|
|
2
|
+
|
|
3
|
+
[WellSky feedback](README.md) · [SDK date contracts](../dates-and-answers.md)
|
|
4
|
+
|
|
5
|
+
Status: the observations below were reproduced in a sandbox tenant on October 22–23, 2026. They concern separate paths. Similar seven-hour differences do not establish one shared server cause or a configured timezone name. These are prepared reports, not confirmed vendor diagnoses.
|
|
6
|
+
|
|
7
|
+
## Complete entry projections omit valid verification rows
|
|
8
|
+
|
|
9
|
+
V2 and V3 complete-enrollment entry projections behaved as though the cutoff was seven hours before the enrollment instant. Generic readback retained the intended row starts.
|
|
10
|
+
|
|
11
|
+
| Row start relative to enrollment | Complete entry result |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Seven hours and one second before | Included |
|
|
14
|
+
| Exactly seven hours before | Included |
|
|
15
|
+
| Six hours, 59 minutes, 59 seconds before | Excluded |
|
|
16
|
+
| One second before or exactly at enrollment | Excluded |
|
|
17
|
+
| One second after enrollment | Excluded |
|
|
18
|
+
|
|
19
|
+
The near-enrollment boundary was tested in income, benefits, insurance, and disability groups. Earlier boundary controls were tested in income. Correcting the mobile write's answer effective date did not change the inclusion pattern.
|
|
20
|
+
|
|
21
|
+
A separate control created an income row through the actual enrollment UI. The observed `addClientRecordsetLinkedToEE` request carried the intended instant, and the UI verified the subassessment. Generic readback confirmed its start and effective date. The complete entry projection still excluded it. This rules out SDK serialization or missing UI enrollment linkage as a sufficient explanation for that control.
|
|
22
|
+
|
|
23
|
+
The alternative enrollment-scoped assessment read included future-start rows as well. It is not an already-filtered entry snapshot. The SDK's `readEnrollmentVerifications` reads generic answers and applies explicit start/end interval checks. It does not move row starts to satisfy the projection.
|
|
24
|
+
|
|
25
|
+
**Ask WellSky:** Which timestamp and timezone conversion determine the complete entry cutoff? Can the projection include the UI-created control at its intended entry instant? Does the same issue affect interim or exit projections? Those additional projections were not established by this boundary experiment.
|
|
26
|
+
|
|
27
|
+
## Mobile answer writes shift the effective date
|
|
28
|
+
|
|
29
|
+
In the controlled fixture, an AddAssessmentAnswer request with `dateEffective=2026-10-18T16:00:00Z` stored a child effective date of `2026-10-18T09:00:00`. Sending `23:00:00Z` through a measured 420-minute correction stored the intended `16:00:00` value. Body row-start dates were controlled independently and retained their intended instants.
|
|
30
|
+
|
|
31
|
+
**Ask WellSky:** Is `dateEffective` interpreted as UTC, a local wall time, or another representation? Can the API preserve an explicit offset and document its response timezone? Is the observed subtraction intended?
|
|
32
|
+
|
|
33
|
+
The SDK exposes `mobileAssessmentDateCorrectionMinutes` for this measured query behavior only. It is not a global date shift and does not fix the complete-entry projection.
|
|
34
|
+
|
|
35
|
+
## DOB serialization can disagree with the UI calendar date
|
|
36
|
+
|
|
37
|
+
Winter and summer REST probes showed the same boundary: `06:59:00Z` became the previous calendar date, while `07:00:00Z` retained the intended date. The browser UI in America/New_York and the REST client date disagreed for a deliberately borderline value. These observations are consistent with a fixed UTC−7 conversion on that path; they do not prove the server's timezone configuration.
|
|
38
|
+
|
|
39
|
+
**Ask WellSky:** Can DOB use an explicit date-only contract without timezone conversion? Which interpretation is authoritative when REST and the UI display different dates?
|
|
40
|
+
|
|
41
|
+
`createDateOfBirth` accepts a calendar date and uses the tested encoding with a browser-date preflight. It rejects incompatible displays rather than silently changing the browser timezone. This behavior must not be applied to enrollment dates, contact dates, or all REST fields.
|
|
42
|
+
|
|
43
|
+
## Correcting DOB at an existing effective timestamp fails
|
|
44
|
+
|
|
45
|
+
A first DOB at a new effective timestamp succeeded. Reusing that timestamp failed with an entity-tracking error for `sp_client`, including unchanged-DOB and quality-only attempts. A new timestamp succeeded, and reusing it failed again. Mobile assessment writes also failed at an existing timestamp. Moving the timestamp by one second avoided the failure but changed history.
|
|
46
|
+
|
|
47
|
+
The supported SDK correction opens the matching latest entry assessment and uses the current UI serializer. It does not create a different effective date. Arbitrary older history corrections and same-timestamp interim or exit corrections remain unsupported.
|
|
48
|
+
|
|
49
|
+
**Ask WellSky:** Can the existing-answer update path update the tracked entity at the original timestamp? What is the documented operation for an in-place historical correction?
|
|
50
|
+
|
|
51
|
+
After a UI-created DOB answer, the mobile assessment projection could return a blank answer while the client API and UI agreed on the saved DOB. **Also ask:** Is that projection expected to expose the value, and can its blank result be corrected or documented? The SDK uses the row's effective timestamp without treating the blank value as proof of absence.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Service collection returns 404 for a client with no services
|
|
2
|
+
|
|
3
|
+
Status: reproduced in a sandbox tenant on October 24, 2026, using Client API V3. V2 and other tenant deployments were not tested for this issue.
|
|
4
|
+
|
|
5
|
+
## Request
|
|
6
|
+
|
|
7
|
+
An authenticated request for an existing, active synthetic client with no service transactions:
|
|
8
|
+
|
|
9
|
+
```http
|
|
10
|
+
GET /client-api-prod/services/{clientId}?perPage=100&startPage=1&total_count=true
|
|
11
|
+
Host: csclientapi.wellsky.com
|
|
12
|
+
x-tenant: your-tenant
|
|
13
|
+
x-version: 3.0
|
|
14
|
+
Authorization: Bearer <redacted>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Use a new synthetic client in an authorized sandbox tenant. Verify the client exists before making this request. Do not substitute a nonexistent client ID.
|
|
18
|
+
|
|
19
|
+
## Expected and actual results
|
|
20
|
+
|
|
21
|
+
Expected: HTTP 200 with a counted empty collection, consistent with the same endpoint's nonempty collection response:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{"count":0,"values":[]}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Actual: HTTP 404. The SDK reported `UpstreamError`, `kind: "http"`, `status: 404`, operation `GET /services/{clientId}`.
|
|
28
|
+
|
|
29
|
+
The client could be opened in the Community Services UI. A fresh, counted GWT query for active service IDs returned zero rows with total zero. The failed REST read therefore did not indicate a missing client. Requests for the user-created shelter examples with existing service records returned HTTP 200 and counted collections.
|
|
30
|
+
|
|
31
|
+
## Reproduction steps
|
|
32
|
+
|
|
33
|
+
1. Create a synthetic client through the normal client-creation workflow.
|
|
34
|
+
2. Open that client in the UI and confirm that no services have been recorded.
|
|
35
|
+
3. Call the endpoint above with valid V3 credentials for the same tenant.
|
|
36
|
+
4. Record the HTTP status and response body without including tokens in the report.
|
|
37
|
+
5. Compare with a client that has at least one active service transaction.
|
|
38
|
+
|
|
39
|
+
## Impact and SDK workaround
|
|
40
|
+
|
|
41
|
+
A collection reader cannot distinguish this response from a missing client, authorization problem, or other routing failure using HTTP status alone. Treating every 404 as an empty collection could let a retry create duplicate services.
|
|
42
|
+
|
|
43
|
+
The shelter workflow only treats this specific first-page 404 as empty after a separate authenticated, client-scoped GWT read proves there are zero active services. It propagates other errors and rejects incomplete reads. This workaround requires a UI session; it is not a change to the generic REST transport's 404 semantics.
|
|
44
|
+
|
|
45
|
+
## Questions for WellSky
|
|
46
|
+
|
|
47
|
+
- Is HTTP 404 for an existing client's empty service collection intentional? If so, please document a response code/body that distinguishes it from missing or inaccessible clients.
|
|
48
|
+
- Could empty collections return HTTP 200 with `count: 0` and `values: []`?
|
|
49
|
+
- Do other collection endpoints or API versions follow the same convention?
|
|
50
|
+
|
|
51
|
+
This report intentionally omits credentials, client demographics, and raw GWT payloads. Private sandbox evidence retains the synthetic IDs for an authorized support follow-up.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Missing DOB and DOB quality trigger a complete-enrollment target error
|
|
2
|
+
|
|
3
|
+
Status: reproduced in a sandbox tenant on October 24, 2026, in Client API V2 and V3. Other tenant deployments were not tested. An initial read-only comparison was followed by DOB-only tests on two new synthetic clients and DOB-quality-only tests on two more. Existing client 579 and the original comparison records were not changed.
|
|
4
|
+
|
|
5
|
+
## Summary for WellSky
|
|
6
|
+
|
|
7
|
+
`GET /enrollments/complete/680` for client 579 returns HTTP 400 with the JSON string value `Non-static method requires a target.` in both API versions. The client, its enrollment list, and three assessment read routes all return HTTP 200. The enrollment also opens through the authenticated UI/GWT reader.
|
|
8
|
+
|
|
9
|
+
The isolated discrepancy is missing DOB information: the failing original has neither `SVPPROFDOB` nor `SVPPROFDOBTYPE`. DOB-only tests first cleared the error. Follow-up tests then showed that an actual birth date is **not required**: recording only `DOBTYPE_DONTKNOW` or `DOBTYPE_REFUSED` also changed the complete read from HTTP 400 to HTTP 200 in both V2 and V3. DOB and its effective timestamp remained empty. Applications must record the client's actual response, never fabricate a date to recover this GET. The exact server-side dereference still requires a stack trace.
|
|
10
|
+
|
|
11
|
+
This is separate from the [grouped-enrollment missing-column error](enrollment-effective-date-column.md). All four existing enrollments in the initial comparison have null `groupId` and `householdId`, and their clients have no household membership in the client response.
|
|
12
|
+
|
|
13
|
+
## Request and comparison
|
|
14
|
+
|
|
15
|
+
```http
|
|
16
|
+
GET /client-api-prod/enrollments/complete/680
|
|
17
|
+
Host: csclientapi.wellsky.com
|
|
18
|
+
Accept: application/json
|
|
19
|
+
x-tenant: your-tenant
|
|
20
|
+
x-version: 3.0
|
|
21
|
+
Authorization: Bearer <redacted>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Repeat with `x-version: 2.0`. Actual response in both versions:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
HTTP 400
|
|
28
|
+
"Non-static method requires a target."
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The raw HTTP comparison ran October 24 at 16:35:38–16:35:45 UTC. It bypassed SDK response processing and used the same bearer token across the comparison. Response headers advertised V3 as supported and V2 as deprecated. No `x-request-id` or `x-correlation-id` was returned in the inspected headers.
|
|
32
|
+
|
|
33
|
+
| Client / enrollment | Entry instant, UTC | V2 complete | V3 complete | V3 client and enrollment list | Active interim reviews, UI/GWT |
|
|
34
|
+
| --- | --- | --- | --- | --- | --- |
|
|
35
|
+
| 579 / 680 | October 18, 16:00 | 400, target error | 400, target error | Both 200 | None |
|
|
36
|
+
| 577 / 679 | October 18, 16:00 | 200 | 200 | Both 200 | Update 151 |
|
|
37
|
+
| 580 / 681 | October 18, 16:00 | 200 | 200 | Both 200 | None |
|
|
38
|
+
| 628 / 719 | October 20, 16:00 | 200 | 200 | Both 200 | None |
|
|
39
|
+
|
|
40
|
+
All four use HUD enrollment type and provider 16951, `TCHC - ECHO - COC - Priority RRH`. All are open, with null exit date, destination, reason for leaving, and exit subgroup. Each has one enrolled client. Fresh UI/GWT reads confirmed the enrollment IDs, provider, type, entry dates, member lists, exit metadata, and review lists without saving forms.
|
|
41
|
+
|
|
42
|
+
Consequences of these controls:
|
|
43
|
+
|
|
44
|
+
- The same provider, type, and entry instant work for 679 and 681. The failure is not universal to that program or date.
|
|
45
|
+
- Absence of an interim does not by itself cause the error: 681 and 719 have none and read successfully.
|
|
46
|
+
- Null exit fields and absence of household grouping also occur in successful controls.
|
|
47
|
+
- V2 does not avoid the error. Neither an SDK parser nor RPC replay is needed to reproduce the failing GET.
|
|
48
|
+
|
|
49
|
+
## Assessment reads and field presence
|
|
50
|
+
|
|
51
|
+
All three routes below returned HTTP 200 and 35 question definitions for each of the four clients:
|
|
52
|
+
|
|
53
|
+
```http
|
|
54
|
+
GET /assessments/{clientId}/HUD_COCESGENTRY_SOESSH_2020?dateEffective={entryDate}
|
|
55
|
+
GET /assessmentsmobile/GetAssessmentAnswers/{clientId}/HUD_COCESGENTRY_SOESSH_2020
|
|
56
|
+
GET /enrollments/assessment/{clientId}/HUD_COCESGENTRY_SOESSH_2020?dataCollectionPoint=entry&providerName=TCHC%20-%20ECHO%20-%20COC%20-%20Priority%20RRH&enrollmentType=HUD&startDate={entryDate}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use `2026-10-18T16:00:00` for 579, 577, and 580, and `2026-10-20T16:00:00` for 628. The instrument is the common API entry assessment; this is not a claim to have inspected every program-specific question.
|
|
60
|
+
|
|
61
|
+
The following counts come from the enrollment-scoped entry route. A scalar counts as populated when at least one of `answer_value`, `answer_value_text`, or `answer_value_code` is non-null and non-empty; zero is a value. Labels are not populated answers.
|
|
62
|
+
|
|
63
|
+
| Client | Populated scalars | Income rows | Non-cash rows | Insurance rows | Disability rows |
|
|
64
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
65
|
+
| 579 | 2 | 0 | 0 | 0 | 0 |
|
|
66
|
+
| 577 | 18 | 15 | 6 | 10 | 8 |
|
|
67
|
+
| 580 | 18 | 15 | 6 | 6 | 6 |
|
|
68
|
+
| 628 | 17 | 15 | 6 | 10 | 8 |
|
|
69
|
+
|
|
70
|
+
These are recorded-row counts from that route, **not** proof that every row is active at entry. Mobile and entry-scoped results can differ; do not treat them as interchangeable snapshots or infer that missing verification rows explain this exception.
|
|
71
|
+
|
|
72
|
+
Client 579's two populated fields are `HUD_RACEETHNICITY` and `HUD_RACEETHNICITYDETAIL`. Its client record represents missing DOB, DOB quality, and veteran status as empty strings, and missing Sex as null. The following 15 scalar fields are populated in all three successful entry controls and empty for 579:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
SVPPROFDOB
|
|
76
|
+
SVPPROFDOBTYPE
|
|
77
|
+
HUD_DISABLINGCONDITION
|
|
78
|
+
HUD_RELATIONTOHOH
|
|
79
|
+
HUD_COCCLIENTLOCATION
|
|
80
|
+
TYPEOFLIVINGSITUATION
|
|
81
|
+
HUD_LENGTHOFSTAY
|
|
82
|
+
HUD_HOMELESSSTARTDATE
|
|
83
|
+
HUD_NUMBEROFTIMESTREETESSH
|
|
84
|
+
HUD_NOMONTHSTREETESSHIN3YRS
|
|
85
|
+
SVP_ANYSOURCE30DAYINCOME
|
|
86
|
+
HUD_TOTALMONTHLYINCOME
|
|
87
|
+
SVP_ANYSOURCE30DAYNONCASH
|
|
88
|
+
HUD_COVEREDBYHLTHINS
|
|
89
|
+
DOMESTICVIOLENCEVICTIM
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This list is a comparison set for debugging, **not a newly established API requirement**. Missing Sex alone is insufficient to explain the failure: client 628 has a null Sex value and reads successfully. Missing translation-assistance answer alone is also insufficient: 628 lacks it. Veteran status, name quality, and SSN quality are empty strings in all four client responses, including the successful controls.
|
|
93
|
+
|
|
94
|
+
### Historical before/after evidence
|
|
95
|
+
|
|
96
|
+
The October 22 boundary test on client 580 / enrollment 681 recorded the target exception before adding baseline profile/entry scalars. A subsequent batch supplied the 15 fields above plus race/ethnicity, Sex, and translation assistance; the complete read then succeeded. Verification rows were not replayed during that recovery.
|
|
97
|
+
|
|
98
|
+
Because 18 fields changed together, that observation cannot isolate DOB, a lookup, relationship to head, or another field as the trigger. The initial comparison preserved client 579's sparse data for vendor reproduction. The controlled tests below then isolated DOB on new synthetic clients, without changing 579.
|
|
99
|
+
|
|
100
|
+
## Projection checks
|
|
101
|
+
|
|
102
|
+
V3 follow-up reads at 16:36:09–16:36:12 UTC tested `$expand=projectStartData`, `projectExitData`, `projectReviewData`, and `enrolledClients` separately on enrollments 680 and 681.
|
|
103
|
+
|
|
104
|
+
- Every requested expansion on 680 returned the same target error.
|
|
105
|
+
- Every requested expansion on 681 returned HTTP 200, with the requested section and base enrollment fields while omitting the other tested sections.
|
|
106
|
+
- An explicitly empty `$expand=` returned HTTP 400 for both: the target error for 680 and a different error for 681. Empty expansion is not a valid workaround established by this test.
|
|
107
|
+
|
|
108
|
+
Omitting entry data from the requested response therefore did not recover 680. This is consistent with failure during shared construction before output selection, but the server execution order is unverified. The experiment does not isolate a particular projection branch.
|
|
109
|
+
|
|
110
|
+
## Controlled isolation: DOB alone clears the error
|
|
111
|
+
|
|
112
|
+
After the initial comparison, two new synthetic clients were created in a sandbox tenant. Each received one HUD enrollment in provider 16951 with the same entry instant as 680, `2026-10-18T16:00:00Z`. Mutations were journaled before submission and were not automatically replayed.
|
|
113
|
+
|
|
114
|
+
| Client / enrollment | Assessment state | V3 complete result |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
| 646 / 733 | No answers | 400, target error |
|
|
117
|
+
| 646 / 733 | Race/ethnicity and detail only | 400, target error |
|
|
118
|
+
| 646 / 733 | Added only `SVPPROFDOB` to the preceding state | 200 |
|
|
119
|
+
| 647 / 734 | No answers | 400, target error |
|
|
120
|
+
| 647 / 734 | Added only `SVPPROFDOB`, with no other answers | 200 |
|
|
121
|
+
|
|
122
|
+
The DOB writes used the existing mobile assessment endpoint, `POST /assessmentsmobile/AddAssessmentAnswer/{clientId}/HUD_COCESGENTRY_SOESSH_2020`, through the SDK encoder and configured effective-date correction. Each DOB request contained exactly one question, `SVPPROFDOB`. The new clients used different valid synthetic birth dates. Readback confirmed that 646 had exactly three populated scalar fields and 647 had exactly one. Neither had verification rows. Their client records still had empty DOB-quality values and null Sex values.
|
|
123
|
+
|
|
124
|
+
Fresh raw HTTP confirmation at 16:38:32–16:38:36 UTC established:
|
|
125
|
+
|
|
126
|
+
- Complete enrollments 733 and 734 returned HTTP 200 in **both V2 and V3**.
|
|
127
|
+
- Enrollment 680 continued to return the target error in both versions, using the same token as the successful reads.
|
|
128
|
+
- Client 579's client, enrollment-list, generic-assessment, mobile-assessment, and scoped-entry responses were unchanged from the initial snapshots.
|
|
129
|
+
- Each new client had exactly one enrollment. UI/GWT reads opened both records and confirmed their provider, entry date, single-member state, absent exits, and empty review lists.
|
|
130
|
+
|
|
131
|
+
The test made seven domain write requests in total: two client creations, two enrollment creations, one race/detail batch on 646, and one DOB answer per new client. An initial harness allowlist blocked a metadata read after creating 646/733; the continuation verified and reused those IDs without repeating creation. No writes were made to the original fixtures.
|
|
132
|
+
|
|
133
|
+
This resolves the field-level discrepancy that the earlier 18-field batch could not isolate. Missing verification rows, DOB quality, race, Sex, relationship to head, and absence of an interim do not independently prevent a successful complete read of fixture 734. That response does **not** mean the sparse enrollment satisfies HMIS data-quality or SDK workflow requirements.
|
|
134
|
+
|
|
135
|
+
The DOB-only experiment did not establish that an actual date was necessary. The quality-only follow-up below answers that question for the two requested responses. The internal mapper or expression responsible for the exception remains unverified; no server stack trace was available.
|
|
136
|
+
|
|
137
|
+
## Quality-only follow-up: unknown or declined DOB also succeeds
|
|
138
|
+
|
|
139
|
+
At 16:42:14–16:42:19 UTC on October 24, two new synthetic clients received individual HUD enrollments in provider 16951 at the same entry instant as 680. Each complete read failed before any DOB or quality answer was recorded. Then one assessment question, `SVPPROFDOBTYPE`, was written using a choice resolved from fresh client-scoped metadata. No DOB field was sent.
|
|
140
|
+
|
|
141
|
+
| Client / enrollment | Only assessment answer added | V2 before → after | V3 before → after |
|
|
142
|
+
| --- | --- | --- | --- |
|
|
143
|
+
| 648 / 735 | `DOBTYPE_DONTKNOW`, Client doesn't know | 400 target error → 200 | 400 target error → 200 |
|
|
144
|
+
| 649 / 736 | `DOBTYPE_REFUSED`, Client prefers not to answer | 400 target error → 200 | 400 target error → 200 |
|
|
145
|
+
|
|
146
|
+
The Client API readback returned an empty string for `svpprofdob` on both clients. Generic assessment readback returned null DOB answer and null DOB effective date. Client DOB quality was `Client doesn't know (HUD)` or `Client prefers not to answer (HUD)`, respectively. Codes were verified exactly; metadata labels had trailing whitespace, so the writes resolved by code.
|
|
147
|
+
|
|
148
|
+
The existing SDK DOB reader independently checked the client API, mobile assessment, and fresh UI Summary. It returned `dateOfBirth: null` and `effectiveDate: null` for both clients. UI/GWT enrollment reads confirmed one enrolled member and one enrollment each. Six successful domain requests created the two clients, two enrollments, and two quality answers. Repeating source-ID client creation with the original inputs performed no additional writes. The harness explicitly rejected any assessment write that was not a single `SVPPROFDOBTYPE` answer.
|
|
149
|
+
|
|
150
|
+
This narrows the defect to the tested state where both DOB and DOB quality are absent. Either the tested DOB-only answer or either tested quality-only response is sufficient to avoid it. It does not prove behavior for every DOB-quality option or every occurrence of this generic exception. Full/approximate DOB quality without a date and other quality codes were not tested.
|
|
151
|
+
|
|
152
|
+
### SDK behavior and regression coverage
|
|
153
|
+
|
|
154
|
+
No SDK runtime workaround is needed for these responses. In an enrollment assessment plan, set `answers.SVPPROFDOBTYPE` to the discovered option code and cover `SVPPROFDOB` with an explicit `notApplicable` explanation that the client did not supply a date. This coverage choice skips the date write; it does not clear a previously recorded DOB. The calendar-date helper is used only for an actual supplied date. Never pass a placeholder date, empty date answer, or a DOB carry-forward when no DOB exists.
|
|
155
|
+
|
|
156
|
+
Regression tests exercise the real workflow and encoder with simulated external services: both quality options, lost scalar acknowledgements, same-key entry and interim retries, changed-intent rejection, and distinct quality-only responses for household members. They assert zero DOB writes and no dependency on the complete-enrollment endpoint. DOB-reader tests preserve a missing date and reject attempts to update it with null, undefined, or an empty string. The same tests are included in clean installed-package verification through public exports.
|
|
157
|
+
|
|
158
|
+
The quality-only live fixtures were created through the SDK client-creation helper and raw enrollment/assessment methods; household and interim quality-only retries were verified locally against simulated services, not through new live household writes in this follow-up.
|
|
159
|
+
|
|
160
|
+
## Reproduction and requested vendor investigation
|
|
161
|
+
|
|
162
|
+
1. Read `/clients/579` and `/enrollments/579`; confirm the existing client and enrollment 680.
|
|
163
|
+
2. Read `/enrollments/complete/680` in V2 and V3; observe the target error.
|
|
164
|
+
3. Compare complete enrollments 679 and 681 with the same credentials. They share provider, type, and entry time and succeed.
|
|
165
|
+
4. Read the three assessment routes above for client 579. They return its sparse answers without this exception.
|
|
166
|
+
5. Compare 733 and 734, which now succeed after DOB-only changes. Fixture 734 has DOB as its only assessment answer.
|
|
167
|
+
6. Compare 735 and 736, which succeed with no DOB and only the unknown/declined quality response.
|
|
168
|
+
7. Inspect the server stack trace for 680. Identify the missing DOB/DOB-quality target, mapping, or expression and whether V2 and V3 share it. A vendor regression should compare neither field populated, DOB only, unknown quality only, and declined quality only.
|
|
169
|
+
|
|
170
|
+
Please clarify whether incomplete entry answers are intended to be readable. Expected behavior is a complete-enrollment response with missing answers represented explicitly, or a documented, field-specific validation error. A generic target exception gives applications no reliable recovery action. Please include absent DOB and unknown/declined DOB cases in regression coverage. Both unknown and declined responses already return successful reads without a date in the tested versions. Preserve that behavior while fixing the unhandled case where both fields are missing.
|
|
171
|
+
|
|
172
|
+
## Application handling and limits
|
|
173
|
+
|
|
174
|
+
Use the successful enrollment list to establish that enrollment 680 exists. Read recorded answers through the assessment API and use the SDK's date-aware verification reader when active-at-date filtering is needed. The authenticated UI/GWT reader provides enrollment/member/review metadata. These are separate reads, not a guarantee of an atomic replacement for the complete endpoint.
|
|
175
|
+
|
|
176
|
+
Never create a replacement enrollment, add an interim, shift dates, or invent a DOB merely because this GET fails. If the actual DOB is known and recording it is authorized, the existing DOB helper can save it; the controlled tests show that a saved DOB clears this failure in these fixtures. If the client does not know or prefers not to answer, record that actual quality response and leave DOB absent; both cases read successfully in the controlled tests. Otherwise use alternate reads and report the upstream defect. Preserve duplicate-protection state. No SDK runtime change was made for this investigation.
|
|
177
|
+
|
|
178
|
+
Private evidence retains the request/status matrix, field-presence comparison, projection results, and sanitized UI/GWT metadata. This shareable report excludes credentials, client demographics, and raw authenticated payloads. The initial comparison comprised 38 REST GETs and four UI/GWT enrollment reads. Controlled writes were followed by 21 raw HTTP confirmation reads, field-by-field assertions, and two additional UI/GWT enrollment reads. Server code and the database were not inspected. The later quality-only evidence is retained separately, including before/after V2/V3 statuses and blank-DOB UI readback. Both date-only and the two quality-only responses resolve the tested failure; the internal exception source remains for WellSky to diagnose.
|