Migrate from 0.7 to 0.8
0.8 removes the compatibility paths the v2 layout (0.4) and the auth hardening (0.5) kept for callers written before them. A module that already follows the 0.3 → 0.4 and 0.4 → 0.5 guides has nothing to change.
Checklist
| Area | What to do | Section |
|---|---|---|
| Dependencies | Raise @antelopejs/interface-dms to >=0.8.0 <1.0.0 | Dependencies |
| Row actions | Write isVisible, not visible, on a custom row action | Row actions |
| Invitations | Send emails: [...], not email, to the Members invite route | Invitations |
| Sessions | Call the Security page's session routes, not the profile ones | Sessions |
| Module tests | Import ResolveInviteAvailability from invite-extensions/internal/availability | Invite availability |
| Request tenant | Nothing behind a DMS auth decorator; a custom provider uses resolveRequestTenantId | Request tenant |
| KPI cards | Set showPreviousValue: false on a card that must stay compact | KPI cards |
| Saved views | Re-save a view filtering a multiple relation with is | Multiple relations |
Dependencies
{
"dependencies": {
"@antelopejs/interface-dms": ">=0.8.0 <1.0.0"
}
}
Row actions read isVisible only
The backend serializes an inline row action as isVisible. The frontend no longer honours the former visible spelling on a CustomRowAction:
// Before
{ id: "open", label: "$app.open", target, visible: true }
// After
{ id: "open", label: "$app.open", target, isVisible: true }
The invite route takes a list
POST /dms/pages/settings/workspace/members/invite no longer reads a single email as a one-address list: a body without emails is refused (400, emails).
// Before
await $authFetch(inviteUrl, { method: "POST", body: { email: "[email protected]", roles, language, asTenantOwner: false } });
// After
await $authFetch(inviteUrl, { method: "POST", body: { emails: ["[email protected]"], roles, language, asTenantOwner: false } });
Sessions live on the Security page
The profile page's duplicate session routes are gone. Use the Security page's:
| Removed | Use |
|---|---|
GET /dms/pages/settings/user/profile/sessions | GET /dms/pages/settings/user/security/sessions |
DELETE /dms/pages/settings/user/profile/sessions/:id | DELETE /dms/pages/settings/user/security/sessions/:id |
DELETE /dms/pages/settings/user/profile/sessions | DELETE /dms/pages/settings/user/security/other-sessions (keeps the caller signed in); a password reset signs every device out |
Invite availability has one import path
internal.ResolveInviteAvailability is no longer re-exported from @antelopejs/interface-dms/invite-extensions. A module test that resolves availability imports it where the DMS does:
// Before
import { internal } from "@antelopejs/interface-dms/invite-extensions";
await internal.ResolveInviteAvailability(context);
// After
import { ResolveInviteAvailability } from "@antelopejs/interface-dms/invite-extensions/internal/availability";
await ResolveInviteAvailability(context);
The request tenant comes from a verified credential
getRequestTenantId(ctx) no longer decodes the bearer token's tenantId without checking its signature. It returns the tenant bound by a verified credential, else DEFAULT_TENANT_ID: a forged token naming another workspace gets the default tenant, never that workspace.
The DMS auth decorators (AuthUser, AuthRawUser, IfAuthUser, AuthOwnerOnly, AuthUserWithPermission), the tenant guards (AuthTenantMember, AuthTenantOwner, authenticateTenantRequest) and authenticateRequestUser bind it, and TenantScopedModel verifies the token itself. A route using them needs no change. IfAuthUser with a valid token now gives that token's tenant; with none, the default tenant, as before.
A route that read the tenant without any of them, or a provider of your own resolved before the auth decorator, changes:
// Before: the tenant claim of any token, signed or not
SetParameterProvider(target, key, index, (ctx) => GetModel(MyModel, getRequestTenantId(ctx)));
// After: verifies the token first, DEFAULT_TENANT_ID without a valid one
SetParameterProvider(target, key, index, async (ctx) => GetModel(MyModel, await resolveRequestTenantId(ctx)));
@antelopejs/interface-dms no longer depends on jsonwebtoken or @antelopejs/interface-auth.
KPI cards show the compared figure
showPreviousValue defaults to true: a KpiCard whose data carries previousValue prints it beside the change, formatted as the value (+12.4 % vs €42,900). A card that must stay compact sets it to false:
KpiCard({ fetchUrl: "/api/sales/kpi", showPreviousValue: false });
A multiple relation filters with include
A RelationType or CascaderRelationType with multiple: true offers include / exclude (and is_empty / is_not_empty) instead of is / is_not, which compared the whole array of ids and never matched one row. A saved view or a link filtering such a relation with is: (?filter_crew=is:<id>) now lists nothing: save the view again, or write include:<id>. A single relation is unchanged.
Migrate from 0.4 to 0.5
What a module or client written for @antelopejs/interface-dms 0.4 checks or changes when the permission, settings and account-security changes land.
Overview
Who may sign in, what each user may see and do, and whose data they reach — the auth, permission and tenancy model of the DMS.