Auth-RBAC · Access Matrix

Матрица доступа по эндпоинтам admin-bff для каждой роли. Дополнение к permissions-matrix.md (исходный backlog).

Роли стенда

РольPermissions countScope
Администратор (admin@erp.local)50+all_franchise
Менеджер ТТ (ivan@test.local)413 ТТ
Курьер (petr@test.local)41 ТТ (Арбат)
Кассир (anna@test.local)(admin-login отказан)через PIN на POS

Курьер permissions: customers.create_quick, customers.read, orders.read, pos.access.

Findings

IDSeverityTitle
F11Manager scope содержит ТТ другого ЮЛ — by-design
F12Cashier admin-login отказан — by-design
F13🔴RBAC read-leak: 7 эндпоинтов доступны без permissions у Курьера
F14🔴Refunds доступны Курьеру без pos.refund (в составе F13)
F15🔴HR-эндпоинты → 500 для всех ролей (4 шт)
BUG-013🔴Manager → Юр.лица 403 (по спеке: read по permission)
BUG-014🔴Manager → ТТ 403 (по спеке: своя ТТ)
BUG-015🔴Создание ТТ → 403 для Franchisee
BUG-016🔴Manager → Склад 403 (на самом деле 404 — F16)
BUG-017🔴Manager → Заказы 403
BUG-049🔴Стоп-листы → 403 у Manager

Матрица read-доступа Курьер vs Manager (session 2026-05-05)

✅ корректно 403 (Курьер) / 200 (Manager с permission):

EndpointКурьер ожиданиеКурьер фактManager ожиданиеManager факт
GET /stores403403 ✅200200 ✅
GET /legal-entities403403 ✅403403 ✅
GET /employees403403 ✅200200 ✅
GET /catalog/products403403 ✅200200 ✅
GET /catalog/categories403403 ✅200200 ✅
GET /catalog/price-lists403403 ✅200200 ✅
GET /catalog/menu-availabilities403403 ✅200200 ✅
GET /modifier-groups403403 ✅200200 ✅
GET /orders?store_id=Арбат200 (своя ТТ)200 ✅200200 ✅
GET /orders?store_id=Бауманская403 (не в scope)403 ✅200 (в scope)200 ✅

F13 leak — Курьер видит без permissions:

EndpointPermission которого нетКурьер факт
GET /catalog/kitchen-stationskds.access200 (4 шт)
GET /kds/deviceskds.access200 (8 шт)
GET /kds/settingskds.access / kds.settings.edit200
GET /pos/devicespos.settings.edit200 (13 шт)
GET /kitchen-queue?store_ids=Xkds.access200 — финансовая чувствительность
GET /refundspos.refund200 (4 шт)
GET /external-menusmenu.read200

F15 — 500 вместо 403/200 (для всех ролей):

EndpointЧто должноЧто происходит
GET /payroll200 (с perm) / 403 (без)500 INTERNAL_ERROR
GET /shift-templates200 / 403500
GET /shift-records200 / 403500
GET /schedules200 / 403500

Mutation RBAC работает корректно:

ЗапросPermission нуженРезультат под Manager
PATCH /catalog/productsmenu.edit (Manager НЕТ)403 «No permission to edit catalog» ✅
POST /catalog/categoriesmenu.edit403 ✅
DELETE /catalog/productsmenu.edit403 ✅
PATCH /kds/settingskds.settings.edit (Manager ЕСТЬ)200 ✅

Тест-кейсы

TC-RBAC-080 — Cashier ТТ-A POST orders ТТ-B → 403

Status: ⏳ partial (нужна Cashier-PIN-сессия) · TC-CHAIN-080

TC-RBAC-081 — Cashier scope-фильтр на orders

Status: ✅ pass · TC-CHAIN-081 Курьер petr@ → GET /orders без фильтра → видит только свою ТТ (Арбат).

TC-RBAC-082 — KDS-оператор видит только свою ТТ

Status: ◯ todo (требует разделения KDS-PIN на ТТ) · TC-CHAIN-082

TC-RBAC-083 — Manager POST /orders/{id}/complete

Status: ◯ todo · TC-CHAIN-083

TC-RBAC-084 — Manager mutation без permission → 403

Status: ✅ pass · TC-CHAIN-084

TC-RBAC-085 — Cashier cancel чужого заказа → 403

Status: ◯ todo · TC-CHAIN-085

TC-RBAC-086 — Franchisee видит ТТ другого ЮЛ → 403

Status: ⛔ blocked (нет creds Franchisee) · TC-CHAIN-086

TC-RBAC-087 — PIN без pos.access → отказ

Status: ◯ todo · TC-CHAIN-087

TC-RBAC-088 — Cashier admin-login → отказ

Status: ✅ pass by-design (F12) · TC-CHAIN-088 Anna admin-login → INVALID_CREDENTIALS

TC-RBAC-013 — RBAC read-leak регрессия (после фикса F13)

Status: verify-needed Прогнать таблицу 7 эндпоинтов под Курьером → все 403.

Snippets

# Логин Курьером (пароль — см. private/creds.md)
PETR=$(curl -sS -X POST $B/auth/login -H "Content-Type: application/json" \
  -d "{\"email\":\"petr@test.local\",\"password\":\"$PETR_PASS\"}" \
  | node -e "let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>console.log(JSON.parse(s).data.access_token))")
 
# Регресс F13
for ep in catalog/kitchen-stations kds/devices kds/settings pos/devices "kitchen-queue?store_ids=fe4b54a9-2cc1-458f-9d0e-338bbc51df76" refunds external-menus; do
  printf "%s => %s\n" "$ep" "$(curl -sS -o /dev/null -w '%{http_code}' "$B/$ep" -H "Authorization: Bearer $PETR")"
done
# После фикса F13 — все должны быть 403