Skip to content

Release OpenSPP v4 - #1805

Merged
josephjclark merged 28 commits into
mainfrom
openspp-v4
Sep 29, 2026
Merged

josephjclark merged 28 commits into
mainfrom
openspp-v4

Conversation

@josephjclark

Copy link
Copy Markdown
Collaborator

Release branch for #1792

gonzalesedwin1123 and others added 28 commits September 24, 2026 14:37
OpenSPP2 runs on Odoo 19, which deprecates JSON-RPC (removal is scheduled
for Odoo 20), and JSON-RPC bypasses spp_api_v2's consent, scopes and audit.
v4 talks to /api/v2/spp with OAuth2 client credentials instead.

- Replace odoo-await with the common request helper; add Utils.js
  (token once per run, tolerant error parsing, identifier encoding,
  search result unwrapping for SearchResult and FHIR Bundle responses)
- Keep the v1 operation names; drop getArea/searchArea (no Area resource)
  and callbacks; operations now throw on errors
- Identifiers are system|value; membership functions take typed
  Individual/ or Group/ references
- Guard enroll/unenroll against OpenSPP2 resolving memberships by
  beneficiary only, and check a group exists before group searches
  (OpenSPP/OpenSPP2#554)
- MockAgent unit tests for every operation and helper
- Major changeset with a v3 to v4 migration guide
- Move private helpers (assert*, read/search/create/patchResource,
  listMemberships, findMembership, putMembership) to Utils.js
- Throw on v3 Odoo domain queries, which OpenSPP ignored and so
  returned every record
- Throw on v3 limit/order options (use count/sort) instead of
  silently dropping them
- getPrograms takes one options object; throw on offset/limit/order
  since programs only page with a cursor
- Inline the membership role system; drop header notes and link the
  REST API v2 reference from the README
- Add paging before/after examples to the migration guide
searchGroup throws on sort and lastId, and searchIndividual/getGroupMembers throw on lastId, since OpenSPP2 silently drops them. Document that searchGroup offset and type are not yet honoured by OpenSPP2 (#555, #565).
Add a per-function scope and module table (the old example scope group:search is not what searches check), paging rules with a loop that follows page.next, and an errors section. Fix sort examples to use birthDate: OpenSPP falls back to name for unknown sort fields, so -birthdate sorted by name.
… 2026.09

Following the next link can skip records under consent filtering (fetch_with_consent advances past the whole over-fetched batch), so the paging example now steps offset by count and de-duplicates. Create does not return 409 for a used identifier on 2026.09, missing individuals/groups return 403 for consent-requiring clients, and only the token endpoint is rate limited (5/min, 50/day). Scope table lists search alternatives and group:read for group filters.
…nores

OpenSPP sorts individuals by name for any sort value other than name, birthDate or lastUpdated, and /ServicePoint drops _sort, _lastId, _elements and _extensions, so these now throw instead of returning silently different results.
…SPP2 2026.09

OpenSPP2 2026.09 matches group and membership-role against any membership, ignores unknown role codes and unresolvable member filters (returning every record), replaces roles on addToGroup, and does not store removeFromGroup reason or unenroll exitReason. The 403 hint now reflects that not-found returns 403 only for consent-requiring clients.
OpenSPP caps each search query at 100 rows, so with count above 50 consent-hidden records end paging early (at 100, one hidden record does): recommend count 50. Credit open PR #555 only with what it fixes (group former members, stale removed status, member references, per-program memberships), not the group/role cross-match. Tokens are fetched once per workflow step, not per run.
Clarify that the adaptor still refuses multi-program membership updates on #555, give the exact early-end threshold for count above 50, version-qualify the member and role notes, and skip records without identifiers in the paging example.
…mber

OpenSPP2 #555 also returns 409 for an identifier that matches more than one registrant; treating every 409 as an existing member sent a PATCH that failed with a misleading error. Test fixtures now use a real role code and the startDate/active|inactive shapes OpenSPP returns.
Open PR #555 now fixes consent paging (next no longer skips, short pages keep next), requires the role on the same group membership, rejects unknown role codes with 422, fixes PATCH gender, and returns 403 instead of 500 for getPrograms without scope. Notes say which behaviour is 2026.09 and which is #555.
Documents the getPrograms filters and cursor paging as a typedef, as asked in review. lastId accepts a number or the string from the next link.
… options

offset and limit point to the count/lastId cursor, while order says programs cannot be sorted, instead of one message that told order users to set a page size.
…the response

As asked in review, the Utils helper no longer returns an operation or resolves references. Each search operation in Adaptor.js resolves its own query and options and calls prepareSearchState.
…tion

Utils.js now has no helpers that return operations or resolve references, matching the searchResource change. getIndividual, getGroup, getProgram, createIndividual, createGroup, updateIndividual and updateGroup resolve their own arguments and call prepareNextState.
Document the one-head rule, #570 (removed members cannot be re-added, and 2026.09 reports the ended membership instead of failing), enroll failing when a membership is hidden, unresolvable references and the loose identifier filter on 2026.09, and #555 behaviour for shared identifiers in search filters. Correct the early-end threshold, the stepping claim, the ifMatch scope, the per-process rate-limit counter and the addToGroup 409 comment.
OpenSPP checks one head per group in an onchange handler, which only runs in its forms; the API accepts a second head on 2026.09 and on #555 (checked live).
The per-page read limit is 3 x count for count up to 50 and 100 above that; #570 on 2026.09 only returns the ended membership until the membership repair runs; shared-identifier filters make enroll fail with 403 and unenroll with "is not a member"; 409 with ifMatch can also mean a shared identifier on #555; stepping by count is exact for individuals.
Add shared test helpers: createMockServer captures common's mock client
log line, assertAllMocksUsed fails a test with unused interceptors, and
jsonBody returns false on a mismatch as undici expects instead of
throwing, which broke unrelated requests after a query-string match.
runWithState replaces the fn() setup step, and each run mocks exactly
one token response.
Rename tests whose names claimed checks they didn't make, assert full
error messages, and add tests for startDate, endedDate, enrollmentDate,
exitReason, object roles, If-Match, paged memberships and the
membership helpers. Every deliberate source mutation in the check now
fails the suite.
Options such as sort on groups, lastId outside programs, v3 limit and
order, and unknown sort fields now log a warning and the job carries on.
Filters that OpenSPP would drop, returning every record, still throw.
The create identifier check is removed: OpenSPP already rejects it with
422.
addToGroup no longer falls back to a PATCH on OpenSPP's 409, which
relied on the wording of its error. It sends one request and surfaces
the 409; role changes go through request.
Public docs no longer track OpenSPP releases or upstream pull requests,
and the paging walkthrough is removed. Search parameters and resource
fields link to the OpenSPP API docs. The AI directive comment blocks are
removed.
State what enroll and unenroll return when nothing changes, that
unenroll throws without a membership, that OpenSPP doesn't save reason
or exitReason, and that a role change through request needs a
CodeableConcept.
jsdoc2md renders parameters as markdown table rows, where an unescaped
pipe inside system|value split the cell and cut off the value.
feat(openspp): rebuild adaptor on the OpenSPP2 REST API v2 (4.0.0)
@josephjclark josephjclark changed the title Release Openspp v4 Release OpenSPP v4 Sep 29, 2026
@josephjclark
josephjclark merged commit 0e2045d into main Sep 29, 2026
5 checks passed
@josephjclark
josephjclark deleted the openspp-v4 branch September 29, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

2 participants