On production the Accounts section failed to load with x:Account/query: unsupportedFilter - type.
The list query sent {"type": "User"}. Stalwart keys a filter by the property's name on the object, which for the discriminator is @type. An unrecognised name comes back as unsupportedFilter with just that name as the description, and the whole query fails. The fix sends {"@type": "User"}; the groups lookup behind the panel uses the same function.
The mock accepted the wrong name, which is how this shipped. It now refuses any filter name the real server doesn't index for that object (from the registry's index list in the 0.16.22 source), with the same error shape.
Checked against production
Read-only JMAP calls from a signed-in admin session on ihasmail.com (v2026.9.13+pr335):
Permission names from /api/account are camelCase (641 of them, none kebab-case), which settles one KNOWN-ISSUES item.
Admin x: calls work with the proxied Basic credential, which settles another.
Account shape matches the code: credentials {"0": Password}; aliases, group memberships and quotas as objects; maxDiskQuota.
Domain shape matches: the zone file is name IN TYPE value with a parenthesised split TXT, and every line matched the format the parser reads; it includes 16 TLSA records. A domainId filter on x:DkimSignature/query works.
Domains page: loads all 11 domains.
No writes were made. KNOWN-ISSUES.md is left for the planned follow-up after live testing.
Testing
New tests:
queryAccounts sends {"@type": ...}, pinned against the exact request;
the mock refuses type the way the live server does, and accepts the indexed names.
## Summary
On production the Accounts section failed to load with `x:Account/query: unsupportedFilter - type`.
The list query sent `{"type": "User"}`. Stalwart keys a filter by the property's name on the object, which for the discriminator is `@type`. An unrecognised name comes back as `unsupportedFilter` with just that name as the description, and the whole query fails. The fix sends `{"@type": "User"}`; the groups lookup behind the panel uses the same function.
The mock accepted the wrong name, which is how this shipped. It now refuses any filter name the real server doesn't index for that object (from the registry's index list in the 0.16.22 source), with the same error shape.
## Checked against production
Read-only JMAP calls from a signed-in admin session on ihasmail.com (v2026.9.13+pr335):
- `{"type": "User"}` → `unsupportedFilter`; `{"@type": "User"}` → 5 users; `{"@type": "Group"}` → 0.
- **Permission names** from `/api/account` are camelCase (641 of them, none kebab-case), which settles one KNOWN-ISSUES item.
- **Admin `x:` calls** work with the proxied Basic credential, which settles another.
- **Account shape matches the code:** credentials `{"0": Password}`; aliases, group memberships and quotas as objects; `maxDiskQuota`.
- **Domain shape matches:** the zone file is `name IN TYPE value` with a parenthesised split TXT, and every line matched the format the parser reads; it includes 16 TLSA records. A `domainId` filter on `x:DkimSignature/query` works.
- **Domains page:** loads all 11 domains.
No writes were made. KNOWN-ISSUES.md is left for the planned follow-up after live testing.
## Testing
- **New tests:**
- `queryAccounts` sends `{"@type": ...}`, pinned against the exact request;
- the mock refuses `type` the way the live server does, and accepts the indexed names.
- **Checks:**
- `npm run typecheck`: clean;
- `npm test -w server`: 188/188;
- `npm test -w web`: all pass.
## Translations
No user-visible strings added or changed.
**Merged** 2026-09-13 as coffey-labs/ihasmail@93c9660421f2
<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.
Summary
On production the Accounts section failed to load with
x:Account/query: unsupportedFilter - type.The list query sent
{"type": "User"}. Stalwart keys a filter by the property's name on the object, which for the discriminator is@type. An unrecognised name comes back asunsupportedFilterwith just that name as the description, and the whole query fails. The fix sends{"@type": "User"}; the groups lookup behind the panel uses the same function.The mock accepted the wrong name, which is how this shipped. It now refuses any filter name the real server doesn't index for that object (from the registry's index list in the 0.16.22 source), with the same error shape.
Checked against production
Read-only JMAP calls from a signed-in admin session on ihasmail.com (v2026.9.13+pr335):
{"type": "User"}→unsupportedFilter;{"@type": "User"}→ 5 users;{"@type": "Group"}→ 0./api/accountare camelCase (641 of them, none kebab-case), which settles one KNOWN-ISSUES item.x:calls work with the proxied Basic credential, which settles another.{"0": Password}; aliases, group memberships and quotas as objects;maxDiskQuota.name IN TYPE valuewith a parenthesised split TXT, and every line matched the format the parser reads; it includes 16 TLSA records. AdomainIdfilter onx:DkimSignature/queryworks.No writes were made. KNOWN-ISSUES.md is left for the planned follow-up after live testing.
Testing
queryAccountssends{"@type": ...}, pinned against the exact request;typethe way the live server does, and accepts the indexed names.npm run typecheck: clean;npm test -w server: 188/188;npm test -w web: all pass.Translations
No user-visible strings added or changed.
Merged 2026-09-13 as coffey-labs/ihasmail@93c9660421
Rebuilt from: git history, session transcript.