From 61d44cb0d4652ccb79224eb3de4da086c798c968 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 8 Mar 2026 12:31:52 +1300 Subject: [PATCH] Add dynamic groups gotcha: PUT returns 200 but changes don't persist Dynamic (smart) groups with isDynamic: true have their membership computed from ruleSets. The API silently accepts PUT requests that include dynamic groups and returns them in the response, but the changes never persist. Discovered after 611 member updates appeared successful but had no effect. Also documents that group color field cannot be empty (422). Co-Authored-By: Claude Opus 4.6 --- docs/gotchas.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/gotchas.md b/docs/gotchas.md index 39df7c0..f34aebb 100644 --- a/docs/gotchas.md +++ b/docs/gotchas.md @@ -107,10 +107,62 @@ client._request("PATCH", f"/member/{member_id}", json={"groups": [...]}) client._request("PUT", f"/member/{member_id}", json={"groups": ["abc123"]}) ``` -> **Note:** PUT requires `firstName`, `lastName`, and `gender` as mandatory fields. GET the member first to preserve existing values. +> **Note:** PUT requires `firstName`, `lastName`, and `gender` as mandatory fields. GET the member first to preserve existing values. The `color` field on each group object **cannot be empty** — an empty string returns 422 (`string.empty`). Always use the color value from the group definition (`GET /memberGroup`) or from the member's existing groups. > **Tested:** Mar 2026. Round-trip verified (add group → confirm → remove → confirm). + +## Dynamic (Smart) Groups Silently Ignore Manual Updates + +**Verified.** Member groups with `isDynamic: true` (visible in `GET /memberGroup`) have their membership computed automatically from `ruleSets`. Attempting to add or remove a dynamic group via `PUT /member/{id}` will: + +1. Return **200 OK** with the group included in the response body +2. **Not persist the change** — subsequent GET requests may still show the group (cached), but the Hello Club UI will not reflect it, and the membership will revert on the next rule evaluation + +This is a **silent data loss trap** — the API gives every indication of success. + +### How to Detect + +Check `isDynamic` on the group definition before attempting updates: + +```python +groups = client.get("/memberGroup", params={"limit": 100}).json() +dynamic_ids = { + g["id"] for g in groups.get("memberGroups", []) + if g.get("isDynamic") +} + +# Before updating a member's groups, filter out dynamic ones +if target_group_id in dynamic_ids: + print("Cannot manually assign members to dynamic group") +``` + +### Dynamic Group Structure + +```json +{ + "name": "Badminton All", + "color": "#ffb300", + "isDynamic": true, + "ruleSets": [ + { + "rules": [ + { + "type": "group", + "condition": "oneOf", + "prop": "groups", + "value": ["group-id-1", "group-id-2", "group-id-3"] + } + ] + } + ] +} +``` + +Dynamic groups do not appear in the member profile group checkboxes in the Hello Club admin UI — they are managed entirely by rules. + +> **Tested:** Mar 2026. PUT returned 200 with group present in response, but group was not visible in Hello Club UI and did not persist. Confirmed across 611 member updates. + ## Address Format Change The spec documents address fields as `streetNumber` + `streetName`, but the API returns: