6.8 KiB
Groups MVP (Design in Progress)
Status: not implemented. groups.md works out the underlying model (what a group is, how "acting as a group" is authenticated across federation). This document doesn't re-derive any of that; it takes that design as given and asks a narrower question: what is the smallest set of screens and actions that makes groups usable, reusing the UI patterns Toolshed already has for friends and inventory rather than inventing new ones.
Goals
- Ship something a user can actually click through: create a group, add/remove members, and have the group own items, end to end.
- Reuse existing screens and interaction patterns wherever the shape already matches, instead of designing new ones (see below).
- Leave every deferred piece as an explicit non-goal rather than a silent gap, so it's clear what MVP does and doesn't cover.
Non-goals (for now)
- Group-to-group friending, and letting outside users friend a group. groups.md's model supports both, but the only audience for a group's items in MVP is the group's own members; "private" already covers that (see "Availability policy for group items" below). Extending visibility to non-members via the group's own friends list is real, valuable, and deferred as a fast-follow, not designed here.
- Transferring an existing personally-owned item's ownership to a group. MVP only supports creating a new item directly owned by a group. Moving an already-existing item across owners is a separate piece of work (ownership transfer isn't something Toolshed supports for user-to-user either today).
- Deleting a group. MVP has no explicit "delete this group" action. A group's lifecycle is just "created, membership changes over time"; the orphaning guard (a group can't be left with zero members, see groups.md's Known Gaps) means a group that's no longer wanted just sits unused rather than needing a teardown flow.
- Any governance, roles, or per-item permissions. Same non-goal as groups.md: every member has equal, full privileges over the group and everything it owns.
User-facing features
Creating a group
A new "Groups" section, entry point styled like Inventory's "Add" button. The form is just a name;
the handle (#name@yourdomain) is derived from it the same way a username becomes part of a user's
handle. The creator becomes the group's first member automatically — there's no empty-group state
to design for.
My Groups list
A "Groups" nav entry/page, modeled directly on Friends.vue: a table of groups the current user is
a member of (name/handle, member count), each row linking into that group's detail page. No
separate "discover groups you're not in" browsing for MVP — you land in a group by being added to
it, the same way you become friends with someone by request/accept, not by browsing a directory of
all users.
Known limitation: this list only ever queries the member's own home backend, so it only shows groups actually hosted there (groups you created, or joined on your own domain). Membership itself works regardless of which backend hosts the group — a remote member can still be invited, accept, and fully edit/delete the group's items (see "Owning items as a group" below) — but a group hosted on someone else's backend won't show up in your own "My Groups" list, because unlike friendship (which both sides record), group membership is only ever recorded on the group's own home backend, and there's no index anywhere of "which other backends has this identity been added to." Making a remote membership discoverable would need a small personal pointer index (written by the client at join time) plus a handle-based group lookup on the group's own backend; deferred as a fast-follow alongside group-friending.
Group detail page
One page per group, with two sections, each reusing an existing pattern wholesale:
- Members — the add/remove-row pattern from
Friends.vue's friend list: an inline "add member" field (enter a handle,user@domain), and a remove (trash icon) action per row. Any member can add or remove any other member — flat privilege, no confirmation step beyond the orphaning guard (removing the group's last member is blocked, with an error explaining why, rather than silently emptying the group). - Group inventory — the exact table/grid pattern from
Inventory.vue(Name, Availability Policy, Amount, Edit/Delete), scoped to items owned by this group, with the same "Add" button leading into the existing item-creation form (see below).
A "Leave group" action removes the current user from Members; if they're the last member, it's blocked by the same orphaning guard.
Owning items as a group
The existing item create/edit form (InventoryNew.vue / InventoryEdit.vue) gets one new field:
an "Owner" selector, defaulting to "Myself," with the groups you belong to as the other options.
Every other field on that form (tags, properties, availability policy, storage location, quantity)
is unchanged, and a group-owned item behaves exactly like a personally-owned one everywhere else in
the app (edit, delete, detail view) — any member can edit or delete it, the same way the owner can
today.
Where group-owned items show up
The main "Inventory" page stays scoped to items you personally own, unchanged from today. A group's items are visible and managed in exactly one place: that group's detail page. This keeps "my inventory" meaning one thing (what I personally own) and avoids merging two different item lists with different edit semantics into one view for MVP.
Availability policy for group items
The item form's existing Availability Policy field (private/share/lend/rent/sell) is unchanged and applies to group-owned items the same way it does today. Since group-friending is out of scope for MVP (see Non-goals), "share/lend/rent/sell" have no wider audience to expand to yet, only "private" is fully meaningful right now — a private group item is visible to and editable by every group member, which is already the core value the Problem statement in groups.md is after (a shared workshop's members all having a say over shared equipment). The field stays as-is rather than being trimmed down to just "private," so nothing needs to change on it once group-friending ships.
Open scoping call
Deferring group-friending is the one judgment call in this document worth flagging explicitly: it means an MVP group can't yet share an item with anyone outside its own membership, which is a real limitation, not just a simplification. It was scoped out because it pulls in a second piece of UI (a group's own Friends tab, and "who can accept a friend request on the group's behalf") that isn't needed for the core "shared ownership among members" use case to work end to end. Worth confirming this is the right line before building against it.