feat(android): gate affordances on the permission matrix #72

Merged
nalum merged 1 commit from feat/android-affordances-from-matrix into main 2026-08-14 16:56:17 +00:00
Owner

Third part of #61: Android gates affordances on the permission matrix, matching the web.

Android decided create/manage controls from MemberRow.manager — a flat Admin || Member derived from the roles string, the same coarse guess the web carried. It hid controls a role was actually permitted, so a child saw no create buttons even for events, jobs, lists and meals the server allows.

  • New Permissions store (data module) reads the server matrix (GetPermissionMatrix, from #69), caches it in SharedPreferences and hydrates synchronously on start (honest offline), and exposes check(matrix, service, method, roles). It keys on prettified role names, the same shape MemberRow.roles carries, so no enum plumbing reaches the UI.
  • Graph fetches the matrix per session; the composables collect it and gate each affordance on the specific verb it performs.
  • Splits mirror the web: Meals into the library (MealService, child) and rota (MealRotaService, member-only); jobs into create (ItemService.Create, child) and the manager tier (ItemService.Delete, member-only). Lists and events admit the child role; rewards stay member-and-up. Per-item ownership checks (canEditJob, canConvert) are untouched.
  • The now-dead MemberRow.manager property is removed.

Android event editing is deferred to a follow-up (commit D), the same way recurring-event edit is.

Verified: make check passes (:app and :data compile, Go tests, web build, i18n — no new strings).

Part of #61.

🤖 Generated with Claude Code

Third part of #61: Android gates affordances on the permission matrix, matching the web. Android decided create/manage controls from `MemberRow.manager` — a flat `Admin || Member` derived from the roles string, the same coarse guess the web carried. It hid controls a role was actually permitted, so a child saw no create buttons even for events, jobs, lists and meals the server allows. - New `Permissions` store (data module) reads the server matrix (`GetPermissionMatrix`, from #69), caches it in SharedPreferences and hydrates synchronously on start (honest offline), and exposes `check(matrix, service, method, roles)`. It keys on prettified role names, the same shape `MemberRow.roles` carries, so no enum plumbing reaches the UI. - Graph fetches the matrix per session; the composables collect it and gate each affordance on the specific verb it performs. - Splits mirror the web: Meals into the library (`MealService`, child) and rota (`MealRotaService`, member-only); jobs into create (`ItemService.Create`, child) and the manager tier (`ItemService.Delete`, member-only). Lists and events admit the child role; rewards stay member-and-up. Per-item ownership checks (`canEditJob`, `canConvert`) are untouched. - The now-dead `MemberRow.manager` property is removed. Android event editing is deferred to a follow-up (commit D), the same way recurring-event edit is. Verified: `make check` passes (`:app` and `:data` compile, Go tests, web build, i18n — no new strings). Part of #61. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(android): gate affordances on the permission matrix
All checks were successful
check / commits (pull_request) Successful in 6s
check / web (pull_request) Successful in 1m32s
check / go (pull_request) Successful in 2m33s
check / report (pull_request) Successful in 3s
feed0393f3
Android decided create and manage controls from MemberRow.manager, a flat
'Admin || Member' derived from the roles string — the same coarse guess
the web carried, hiding controls a role is actually permitted (a child saw
none). Add a Permissions store that reads the server's matrix
(GetPermissionMatrix, cached and hydrated on start) and a check() that
gates each affordance on the specific verb it performs, mirroring the web.
Meals splits into the library (MealService) and rota (MealRotaService);
jobs split create (ItemService.Create, child) from the manager tier
(ItemService.Delete). Android event editing follows separately. Part of #61.

Test report

Suite Tests Result Skipped
Unit 1330 ✅ pass 1
Integration 83 ✅ pass —

Coverage: 27.7%

Updated by the check workflow · commit 5f37ec9703

<!-- ci-test-report --> ## Test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit | 1330 | ✅ pass | 1 | | Integration | 83 | ✅ pass | — | **Coverage:** 27.7% <sub>Updated by the check workflow · commit 5f37ec9703177e96186c9108383dc556c234ee9d</sub>
nalum force-pushed feat/android-affordances-from-matrix from feed0393f3
All checks were successful
check / commits (pull_request) Successful in 6s
check / web (pull_request) Successful in 1m32s
check / go (pull_request) Successful in 2m33s
check / report (pull_request) Successful in 3s
to 5f37ec9703
Some checks failed
check / commits (pull_request) Successful in 8s
check / web (pull_request) Successful in 1m39s
check / go (pull_request) Successful in 2m48s
android / build (pull_request) Successful in 6m56s
check / report (pull_request) Successful in 4s
android / report (pull_request) Successful in 3s
android / report (push) Has been cancelled
check / commits (push) Has been cancelled
check / go (push) Has been cancelled
check / report (push) Has been cancelled
check / web (push) Has been cancelled
tag / tag (push) Has been cancelled
android / build (push) Has been cancelled
2026-08-14 16:03:14 +00:00
Compare

Android test report

Suite Tests Result Skipped
Unit (debug) 31 ✅ pass 0

Updated by the android workflow · commit 5f37ec9703

<!-- android-test-report --> ## Android test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit (debug) | 31 | ✅ pass | 0 | <sub>Updated by the android workflow · commit 5f37ec9703177e96186c9108383dc556c234ee9d</sub>
nalum changed target branch from feat/web-event-edit to main 2026-08-14 16:56:10 +00:00
nalum merged commit 5f37ec9703 into main 2026-08-14 16:56:17 +00:00
nalum deleted branch feat/android-affordances-from-matrix 2026-08-14 16:56:17 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
eagraiclainne/app!72
No description provided.