[data-reveal]{opacity:1!important;transform:none!important}
Migrate from 0.7 to 0.8
Building

Migrate from 0.7 to 0.8

The compatibility paths @antelopejs/interface-dms 0.8 and the DMS release that implements it remove, with the code before and after.

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

AreaWhat to doSection
DependenciesRaise @antelopejs/interface-dms to >=0.8.0 <1.0.0Dependencies
Row actionsWrite isVisible, not visible, on a custom row actionRow actions
InvitationsSend emails: [...], not email, to the Members invite routeInvitations
SessionsCall the Security page's session routes, not the profile onesSessions
Module testsImport ResolveInviteAvailability from invite-extensions/internal/availabilityInvite availability
Request tenantNothing behind a DMS auth decorator; a custom provider uses resolveRequestTenantIdRequest tenant
KPI cardsSet showPreviousValue: false on a card that must stay compactKPI cards
Saved viewsRe-save a view filtering a multiple relation with isMultiple relations

Dependencies

package.json
{
  "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:

RemovedUse
GET /dms/pages/settings/user/profile/sessionsGET /dms/pages/settings/user/security/sessions
DELETE /dms/pages/settings/user/profile/sessions/:idDELETE /dms/pages/settings/user/security/sessions/:id
DELETE /dms/pages/settings/user/profile/sessionsDELETE /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.