feat: the TUI adopts the permission matrix (#136) #151

Merged
nalum merged 1 commit from feat/tui-matrix into main 2026-08-18 16:44:14 +00:00
Owner

Closes #136. PR 13 of the #137 stack, based on #150.

The TUI was the last surface guessing from role buckets (isAdmin/isManager) — the pattern ADR-0028 retired. It now fetches GetPermissionMatrix at entry (new pkg/client wrapper; falls back to the compiled-in matrix on a network blip so affordances never blank) and gates every control on the verb it performs via appCtx.can(). All four recorded divergences close:

  • Jobs — New job reads Create.standalone (children get the creation the ADR-0031 row grants them); assign reads AssignUser.other, repeat SetRepeat, link RewardService/LinkItem, delete Delete.
  • Rewards — claim-for-other reads Claim.other, so a MEMBER is no longer shown an action the server denies; grant/edit/link/delete split per verb.
  • Calendar — a canManageEvent mirror of RequireEventMember (the verb's row, then membership or the admin bypass) replaces the tier guess that both over- and under-showed.
  • Lists — create/rename/delete/uncheck read their own rows, so children see the list verbs the matrix opens to them.

The Family tab and Admin-tab gate adopt the same verbs (mirroring PR #150's web split), the help lines advertise only granted verbs (absent, not greyed), and isManager is gone — isAdmin survives solely inside guard mirrors whose server rule is itself role-based.

Live-verified in tmux sessions against the deployed cluster: a CHILD's Jobs help now offers "n new" and their Lists tab offers new/rename/delete (the previously hidden grants) while assign/repeat/delete and all reward management stay absent; an ADMIN sees the full set plus the Admin tab. make check green.

🤖 Generated with Claude Code

Closes #136. PR 13 of the #137 stack, based on #150. The TUI was the last surface guessing from role buckets (`isAdmin`/`isManager`) — the pattern ADR-0028 retired. It now fetches `GetPermissionMatrix` at entry (new `pkg/client` wrapper; falls back to the compiled-in matrix on a network blip so affordances never blank) and gates every control on the verb it performs via `appCtx.can()`. All four recorded divergences close: - **Jobs** — New job reads `Create.standalone` (children get the creation the ADR-0031 row grants them); assign reads `AssignUser.other`, repeat `SetRepeat`, link `RewardService/LinkItem`, delete `Delete`. - **Rewards** — claim-for-other reads `Claim.other`, so a MEMBER is no longer shown an action the server denies; grant/edit/link/delete split per verb. - **Calendar** — a `canManageEvent` mirror of `RequireEventMember` (the verb's row, then membership or the admin bypass) replaces the tier guess that both over- and under-showed. - **Lists** — create/rename/delete/uncheck read their own rows, so children see the list verbs the matrix opens to them. The Family tab and Admin-tab gate adopt the same verbs (mirroring PR #150's web split), the help lines advertise only granted verbs (absent, not greyed), and `isManager` is gone — `isAdmin` survives solely inside guard mirrors whose server rule is itself role-based. Live-verified in tmux sessions against the deployed cluster: a CHILD's Jobs help now offers "n new" and their Lists tab offers new/rename/delete (the previously hidden grants) while assign/repeat/delete and all reward management stay absent; an ADMIN sees the full set plus the Admin tab. `make check` green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(tui): affordances from the permission matrix
Some checks failed
check / commits (pull_request) Successful in 7s
check / web (pull_request) Successful in 1m31s
check / go (pull_request) Successful in 2m33s
check / report (pull_request) Successful in 4s
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
43271e76c4
The TUI still guessed from role buckets — the pattern ADR-0028
retired everywhere else — and disagreed with the server in four
places: children were hidden the list and job creation the matrix
grants them, a MEMBER was shown claim-for-other the server denies,
and calendar editing gated on a tier where the server rule is event
membership (#136). The client now fetches GetPermissionMatrix at
entry (falling back to the compiled-in matrix if the fetch blips) and
every tab gates on the verbs it performs, with the same guard mirrors
the web uses — the manager tier through Update.other, claim-for-other
through Claim.other, event editing through membership plus the admin
bypass.

Test report

Suite Tests Result Skipped
Unit 1370 ✅ pass 1
Integration 86 ✅ pass —

Coverage: 27.9%

Updated by the check workflow · commit 43271e76c4

<!-- ci-test-report --> ## Test report | Suite | Tests | Result | Skipped | | --- | --: | --- | --: | | Unit | 1370 | ✅ pass | 1 | | Integration | 86 | ✅ pass | — | **Coverage:** 27.9% <sub>Updated by the check workflow · commit 43271e76c4781068e1d89de64e3a5eef0706d65c</sub>
nalum changed target branch from feat/web-admin-matrix to main 2026-08-18 16:44:08 +00:00
nalum merged commit 43271e76c4 into main 2026-08-18 16:44:14 +00:00
nalum deleted branch feat/tui-matrix 2026-08-18 16:44:14 +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!151
No description provided.