Add the update group endpoint, owner-only #49
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/update-group-endpoint"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes task 76.
PUT /api/groups/{groupId}renames a group, gated by the existingGroupOwnerpolicy viaRequireGroupCapability— Editor/Viewer get 403, non-member/nonexistent group get 404 (ADR-0041).No new ADR: this follows ADR-0041/0043's existing shape with no new architectural decision.
Scope note: the ticket text says "edits a group's name and description", but
groupshas nodescriptioncolumn (onlyplacesdoes — seedocs/data-model.md), andUpdateGroupRequest/GroupResponse/theGroupentity already existed withNameonly, from earlier tickets. I've treated that as stale wording carried over from a template rather than a real requirement, and implemented name-only. Adding a description column is a schema change nobody has decided; flagging it here rather than inventing it.personal_for_user_id:
GroupRepository.UpdateAsync'sSETclause only ever writesnameandupdated_at— there's no way to movepersonal_for_user_idthrough this path, over-posting or not. Covered by an integration test that over-posts the field on a personal group's rename and asserts it's unchanged in the database.Concurrency: no optimistic concurrency check — last write wins, one
UPDATE ... RETURNINGstatement. Acceptable at ADR-0007's hobby scale; documented onGroupRepository.UpdateAsync.Tests: Owner success (200,
updated_atadvances), personal group rename withpersonal_for_user_idunchanged, Editor 403, Viewer 403, non-member 404, nonexistent group 404, blank name 400, unauthenticated 401 — all against a real Postgres viaWebApplicationFactory+ Testcontainers.Verdict: mergeable
Verified:
personal_for_user_idis structurally unwritable through this path —UpdateGroupName'sSETclause and its parameter object carry no such column/property, independent of the unique index; the over-post test proves it end to end. Mutating the route policy toGroupCapability.Memberreddens both the Editor and Viewer 403 tests. 404 vs 403 split matches ADR-0041.UPDATE ... RETURNINGis a single atomic statement returning post-update values, confirmed by the advancingupdated_atassertion. Ran two concurrentUpdateAsynccalls against the same row directly: both complete, the persisted row matches whichever call's own return value, no lost update. Scope is rename-only, no schema script, no other endpoints touched.GroupResponse/UpdateGroupRequestare hand-shaped contracts, no entity on the wire.