Product permissions
This page lists the Clerk permissions that gate product, barcode, and category actions in the web app, and where each one is enforced: in the UI (Nuxt client) or on the server (Nitro routes under apps/web/server/api).
Permissions in use
| Permission | Gates | UI enforcement | Server enforcement |
|---|---|---|---|
org:products:read | Product pages, product list | Page meta of apps/web/pages/[client]/products/index.vue and [id].vue | POST /api/products/by-skus, GET /api/products/export |
org:products:create | Create and import products | apps/web/pages/[client]/products/new.vue, import-products.vue (<Protect> and page meta) | POST /api/products, POST /api/products/bulk, GET /api/products/sku-check, GET /api/products/barcode-check, POST /api/products/:id/barcodes |
org:products:edit | Every edit of an existing product | useProductAccess (canEdit), [id].vue (canEditProduct) | PATCH /api/products/:id, GET /api/products/sku-check, kit, item, level, lock, and variation mutations (see the route table) |
org:products:delete | Delete a product | index.vue (<Protect>) | DELETE /api/products/:id |
org:barcodes:create | Add a barcode | [id].vue (canCreateBarcode) | POST /api/products/:id/barcodes, GET /api/products/barcode-check |
org:barcodes:edit | Edit a barcode | [id].vue (canEditBarcode) | PATCH /api/products/:id/barcodes/:barcodeId, GET /api/products/barcode-check |
org:barcodes:delete | Delete a barcode | [id].vue (canDeleteBarcode) | DELETE /api/products/:id/barcodes/:barcodeId |
org:categories:read | List and resolve categories | — | GET /api/categories, POST /api/categories/resolve |
org:categories:create | Create a category | ProductCommonFields.vue (canCreateCategory), import-products.vue | POST /api/categories |
Permission constants for categories are defined in modules/inventory/src/common/domain/permissions/category.permissions.ts.
Removed permissions
The following permissions are no longer read anywhere in the code. Assigning them has no effect.
| Permission | Replaced by |
|---|---|
org:products:edit_main_fields | org:products:edit |
org:products:edit_grupo | org:products:edit |
org:products:edit_logistics_fields | org:products:edit + organization type + catalog mode (requireLogisticsEdit) |
org:products:edit_extended | org:products:edit (fields); catalog mode setting (catalog tab) |
Catalog rule on top of permissions
Some mutations also require the catalog rule (canEditLogistics in apps/web/utils/products/product-access.ts):
| Catalog mode | Organization type | Logistics fields and barcodes on existing products |
|---|---|---|
| OFF | any | Allowed |
| ON | PARTNER | Allowed |
| ON | VENDOR | Rejected |
On the server this rule is requireLogisticsEdit in apps/web/server/utils/permissions.ts.
| Condition | Status | statusMessage |
|---|---|---|
| Organization cannot be resolved | 403 | No se pudo determinar la organización |
| Rule rejects the caller | 403 | Con el catálogo activo, solo usuarios partner pueden modificar campos logísticos |
Logistics keys checked on PATCH /api/products/:id are listed in Product field access.
Server route table
Routes are under apps/web/server/api/. "Catalog rule" means requireLogisticsEdit runs after the permission check.
Products
| Method and route | Permission | Catalog rule |
|---|---|---|
GET /api/products | none | — |
POST /api/products | org:products:create | — |
POST /api/products/bulk | org:products:create | — |
POST /api/products/by-skus | org:products:read | — |
GET /api/products/export | org:products:read | — |
GET /api/products/kardex | none | — |
GET /api/products/sku-check | org:products:create or org:products:edit | — |
GET /api/products/barcode-check | org:products:create or org:barcodes:create or org:barcodes:edit | — |
GET /api/products/:id | none | — |
PATCH /api/products/:id | org:products:edit | Only when the body contains a logistics key |
DELETE /api/products/:id | org:products:delete | — |
GET /api/products/:id/orders | org:orders:read | — |
GET /api/products/:id/kardex | none | — |
GET /api/products/:id/items | none | — |
PATCH, DELETE /api/products/:id/items/:itemId | org:products:edit | — |
GET /api/products/:id/kits, GET /api/products/:id/kits/:itemId | none | — |
POST /api/products/:id/kits, PATCH, DELETE /api/products/:id/kits/:itemId | org:products:edit | — |
GET /api/products/:id/levels, GET /api/products/:id/levels/:levelId | none | — |
POST /api/products/:id/levels, PATCH, DELETE /api/products/:id/levels/:levelId | org:products:edit | — |
GET /api/products/:id/locks | none | — |
PATCH /api/products/:id/locks/:lockId | org:products:edit | — |
GET /api/products/:id/variations | none | — |
POST /api/products/:id/variations | org:products:edit | — |
Barcodes
| Method and route | Permission | Catalog rule |
|---|---|---|
GET /api/products/:id/barcodes | none | — |
POST /api/products/:id/barcodes | org:barcodes:create or org:products:create | Yes, unless the caller has org:products:create |
PATCH /api/products/:id/barcodes/:barcodeId | org:barcodes:edit | Yes |
DELETE /api/products/:id/barcodes/:barcodeId | org:barcodes:delete | Yes |
POST /api/barcodes/bulk | none | — |
Categories
| Method and route | Permission |
|---|---|
GET /api/categories | org:categories:read |
POST /api/categories | org:categories:create |
POST /api/categories/resolve | org:categories:read |
Query parameters and responses are in Categories API.
Organizations
| Method and route | Permission | Notes |
|---|---|---|
GET /api/organizations/:id | none | Returns the organization with settings.CATALOG_MODE already merged from the partner (see apps/web/server/utils/organizations/organizationContext.ts). |
Barcode actions in the edit page
In apps/web/pages/[client]/products/[id].vue each barcode action requires its org:barcodes:* permission and the catalog rule. org:products:edit is not required for barcode actions. A user with only barcode permissions sees Guardar cambios; the product PATCH is skipped for them and only new barcodes are created.
Related
- Field-by-field rules: Product field access
- Why permissions were simplified: Catalog mode and permissions