TreeMembership was enforced everywhere but had no API/UI to manage members — trees were effectively single-user (breaks NN#8 full-CRUD).
Backend/trees/{id}/members: list (members-only — exposes emails, so non-members never see it even on public trees); add existing user by email (owner-only; 404 no-account, 409 already-member); PATCH role; DELETE. A tree must keep ≥1 owner (demote/remove sole owner → 409). Audited.
Frontend: Members page (owner: add-by-email + role select + remove; others read-only) + sidebar entry.
TreeMembership was enforced everywhere but had no API/UI to manage members — trees were effectively single-user (breaks NN#8 full-CRUD).
**Backend** `/trees/{id}/members`: list (members-only — exposes emails, so non-members never see it even on public trees); add existing user by email (owner-only; 404 no-account, 409 already-member); PATCH role; DELETE. A tree must keep ≥1 owner (demote/remove sole owner → 409). Audited.
**Frontend**: Members page (owner: add-by-email + role select + remove; others read-only) + sidebar entry.
Test covers full lifecycle + guards. **77 passed.**
Closes #145
🤖 Generated with [Claude Code](https://claude.com/claude-code)
TreeMembership was enforced on every read/write but had no API or UI to manage
members — trees were effectively single-user, breaking full-CRUD (NN#8).
Backend (/trees/{id}/members): list (members only — the list exposes emails, so
non-members never see it, even on public trees); add an existing user by email
(owner only, 404 if no such account, 409 if already a member); PATCH role;
DELETE. A tree must always keep ≥1 owner (demote/remove of the sole owner → 409).
All changes audited.
Frontend: a Members page (owner gets add-by-email + per-member role select +
remove; others see a read-only list) and a sidebar entry.
Test covers the full lifecycle + every guard. Suite 77 passed.
Closes#145
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Justin Paul <[email protected]>
justin
merged commit 3a7728f1dc into main2026-06-09 12:43:31 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
TreeMembership was enforced everywhere but had no API/UI to manage members — trees were effectively single-user (breaks NN#8 full-CRUD).
Backend
/trees/{id}/members: list (members-only — exposes emails, so non-members never see it even on public trees); add existing user by email (owner-only; 404 no-account, 409 already-member); PATCH role; DELETE. A tree must keep ≥1 owner (demote/remove sole owner → 409). Audited.Frontend: Members page (owner: add-by-email + role select + remove; others read-only) + sidebar entry.
Test covers full lifecycle + guards. 77 passed.
Closes #145
🤖 Generated with Claude Code
TreeMembership was enforced on every read/write but had no API or UI to manage members — trees were effectively single-user, breaking full-CRUD (NN#8). Backend (/trees/{id}/members): list (members only — the list exposes emails, so non-members never see it, even on public trees); add an existing user by email (owner only, 404 if no such account, 409 if already a member); PATCH role; DELETE. A tree must always keep ≥1 owner (demote/remove of the sole owner → 409). All changes audited. Frontend: a Members page (owner gets add-by-email + per-member role select + remove; others see a read-only list) and a sidebar entry. Test covers the full lifecycle + every guard. Suite 77 passed. Closes #145 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Signed-off-by: Justin Paul <[email protected]>