Backend Core Entitlements
Related documentation: Data ownership · Backend Core Addons · Backend Admin API
Purpose
Section titled “Purpose”Core is the source of truth for company commercial entitlements: base package, add-ons, and restriction packages (negative org overrides). Auth still owns membership permission grants; Core can deny specific permission keys for everyone in a company when an active restriction applies.
GET /internal/companies/{companyId}/entitlements
Section titled “GET /internal/companies/{companyId}/entitlements”Returns the resolved entitlement snapshot for a company, including:
| Field | Meaning |
|---|---|
enabledModules | Union of base package + active add-on modules |
restrictions | Active company restriction package assignments (summary) |
deniedPermissionKeys | Union of Auth permission keys blocked by active restrictions |
deniedPermissionKeys is computed from restriction_package_permissions for every active row in company_restrictions. Persona apps (Promoters BFF/FE) must treat a key in this list as denied for all members, including OWNER, ADMIN, and TENANT_SUPERADMIN, even when Auth granted the key.
Positive access still requires Auth membership grants. Restrictions only subtract capability at the org level.
Restriction packages (catalog)
Section titled “Restriction packages (catalog)”Restriction packages are catalog rows — not add-ons. They do not grant modules; they list permission keys to deny when attached to a company.
Tables (migration 00024_restriction_packages.sql):
restriction_packages—key,name,description,is_activerestriction_package_permissions—(restriction_package_id, permission_key)(Auth keys as plain text; no FK to Auth)company_restrictions— company assignment withstatus, window fields;UNIQUE(company_id, restriction_package_id)
Seed: agencies_contact — “Agencies & artist contacts” — denies promoter.booking.agencies.view. Not auto-attached to any company; operators attach manually from Admin → company Subscriptions.
Internal catalog APIs (machine key)
Section titled “Internal catalog APIs (machine key)”Mirror add-on catalog shape:
GET/POST /internal/catalog/restriction-packagesGET/PATCH/DELETE /internal/catalog/restriction-packages/{id}
Create/update bodies accept permissionKeys: string[] (Auth catalog keys).
Company attach
Section titled “Company attach”POST /internal/companies/{companyId}/restrictions
Body:
{ "restrictionKey": "agencies_contact", "status": "active", "startsAt": "2026-08-12T00:00:00Z", "endsAt": null, "source": "platform_admin", "externalReference": "support_ticket_123"}Detach by posting status: "inactive" (same pattern as add-ons). Successful upsert bumps entitlementVersion.
Subscription summary items
Section titled “Subscription summary items”Company subscription items[] may include kind: "restriction" rows (alongside package and addon). Each restriction item uses the catalog package UUID as id, exposes permissionKeys on the item, and appears in Admin company Subscriptions UI.
Consumer rules (Promoters)
Section titled “Consumer rules (Promoters)”When promoter.booking.agencies.view ∈ deniedPermissionKeys:
- Hide Booking → Agencies nav (owner bypass does not apply)
- Block
/booking/agencies/**and artist Team tab in the Promoters FE - BFF returns 403 on agencies network routes, artist team, and legacy artist contacts when the key is denied — after normal Auth permission checks
Hydration path: Promoters GET /users/init → access.deniedPermissionKeys from Core company context → FE global state deniedPermissionKeys.