Second of the five stacked Administration PRs. This one targets feat/admin-dashboard (#360). The five are meant to merge together, in order.
What it adds: Groups under Directory, next to Accounts. To Stalwart a group is an x:Account with @type: "Group", using the same sysAccountQuery/sysAccountGet permissions, so it follows the Accounts layout: search, pages of 50, a member-count column, and a side panel.
Panel
Display name, address (when creating), other addresses, role, and storage limit. These save together, with only changed fields sent.
Members: search for a person and add them, or remove members one at a time. Each change applies immediately.
Stalwart stores membership on the user, so each add or remove is one update: "memberGroupIds/<group>": true | null. That changes nothing else in the user's set.
You can't add or remove yourself, matching the "can't change your own role" rule.
Role:Default or Custom. From the source, in 0.16 a user's permissions come only from their own roles; a group gives members access to what's shared with it, not permissions. Only roles the viewer could grant are offered.
Delete:
Type-the-address confirmation.
Members are taken out first, then the group is destroyed. This is the same keys-then-domain order Domains uses, since the registry keeps anything another object points to.
A role without sysAccountUpdate isn't offered a delete it could only half finish.
Mock fixes
Groups had a user's roles; they're now Default.
A memberGroupIds filter was accepted but ignored; it's now applied.
A delete refused because members still point to the group came back with the wrong error shape; it now matches the domain case (linkedObjects: [{object, id}]).
The mock now refuses nested groups, and memberships pointing at things that aren't groups.
Not tried live. Prod has no groups and every operation is a write. What was read from source is recorded in KNOWN-ISSUES, including the assumption that deleting a group with members is refused (the UI removes members first either way). I'd like to confirm on the live server with a throwaway group before these merge.
Translation: 35 new strings (2 plurals) in all nine catalogues (1489/1505 each, 16 falling back as before).
Checked
Typecheck, 1249 web and 212 server tests pass, as do build and i18n:check.
New tests cover:
the membership patch shape, and the member-count query;
create payload (no credentials or encryption settings);
delete order, stopping if removing members fails, and the no-members case;
mock filter, pointer, nesting and linked-delete behaviour;
panel guards (can't remove yourself, read-only role, delete blocked without update, delete passing every member).
In Chrome against the mock:
list and counts;
opened Support, added Grace (count 2→3, Office unchanged), removed Alan (3→2);
created "Sales", added a member, deleted it through the dialog ("Its 1 member is taken out…");
Second of the five stacked Administration PRs. This one targets `feat/admin-dashboard` (#360). The five are meant to merge together, in order.
**What it adds:** Groups under Directory, next to Accounts. To Stalwart a group is an `x:Account` with `@type: "Group"`, using the same `sysAccountQuery`/`sysAccountGet` permissions, so it follows the Accounts layout: search, pages of 50, a member-count column, and a side panel.
**Panel**
- Display name, address (when creating), other addresses, role, and storage limit. These save together, with only changed fields sent.
- **Members:** search for a person and add them, or remove members one at a time. Each change applies immediately.
- Stalwart stores membership on the user, so each add or remove is one update: `"memberGroupIds/<group>": true | null`. That changes nothing else in the user's set.
- You can't add or remove yourself, matching the "can't change your own role" rule.
- **Role:** `Default` or `Custom`. From the source, in 0.16 a user's permissions come only from their own roles; a group gives members access to what's shared with it, not permissions. Only roles the viewer could grant are offered.
- **Delete:**
- Type-the-address confirmation.
- Members are taken out first, then the group is destroyed. This is the same keys-then-domain order Domains uses, since the registry keeps anything another object points to.
- A role without `sysAccountUpdate` isn't offered a delete it could only half finish.
**Mock fixes**
- Groups had a user's roles; they're now `Default`.
- A `memberGroupIds` filter was accepted but ignored; it's now applied.
- A delete refused because members still point to the group came back with the wrong error shape; it now matches the domain case (`linkedObjects: [{object, id}]`).
- The mock now refuses nested groups, and memberships pointing at things that aren't groups.
**Not tried live.** Prod has no groups and every operation is a write. What was read from source is recorded in KNOWN-ISSUES, including the assumption that deleting a group with members is refused (the UI removes members first either way). I'd like to confirm on the live server with a throwaway group before these merge.
**Translation:** 35 new strings (2 plurals) in all nine catalogues (1489/1505 each, 16 falling back as before).
**Checked**
- Typecheck, 1249 web and 212 server tests pass, as do build and i18n:check.
- New tests cover:
- the membership patch shape, and the member-count query;
- create payload (no credentials or encryption settings);
- delete order, stopping if removing members fails, and the no-members case;
- mock filter, pointer, nesting and linked-delete behaviour;
- panel guards (can't remove yourself, read-only role, delete blocked without update, delete passing every member).
- In Chrome against the mock:
- list and counts;
- opened Support, added Grace (count 2→3, Office unchanged), removed Alan (3→2);
- created "Sales", added a member, deleted it through the dialog ("Its 1 member is taken out…");
- no console errors.
**Merged** 2026-09-15 as coffey-labs/ihasmail@5a7a8019e94f
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
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.
Second of the five stacked Administration PRs. This one targets
feat/admin-dashboard(#360). The five are meant to merge together, in order.What it adds: Groups under Directory, next to Accounts. To Stalwart a group is an
x:Accountwith@type: "Group", using the samesysAccountQuery/sysAccountGetpermissions, so it follows the Accounts layout: search, pages of 50, a member-count column, and a side panel.Panel
"memberGroupIds/<group>": true | null. That changes nothing else in the user's set.DefaultorCustom. From the source, in 0.16 a user's permissions come only from their own roles; a group gives members access to what's shared with it, not permissions. Only roles the viewer could grant are offered.sysAccountUpdateisn't offered a delete it could only half finish.Mock fixes
Default.memberGroupIdsfilter was accepted but ignored; it's now applied.linkedObjects: [{object, id}]).Not tried live. Prod has no groups and every operation is a write. What was read from source is recorded in KNOWN-ISSUES, including the assumption that deleting a group with members is refused (the UI removes members first either way). I'd like to confirm on the live server with a throwaway group before these merge.
Translation: 35 new strings (2 plurals) in all nine catalogues (1489/1505 each, 16 falling back as before).
Checked
Merged 2026-09-15 as coffey-labs/ihasmail@5a7a8019e9
Rebuilt from: git history, session transcript.