# Admin · Support content — Parity matrix

Demo (canonical): `portals/admin/SupportContent.tsx`. Ours: Yii2 `backend/` + `common/`.

| # | Demo behavior | Demo ref | Our ref | Status | Note |
|---|---|---|---|---|---|
| 1 | Single "Support & content" admin screen with 2 segmented tabs (FAQs / Contact Us) | SupportContent.tsx:41-58 | — | missing | Ours splits into separate `/faq` and `/contact-us` menu items; no tabs |
| 2 | FAQ = `{question, answer}` pair | SupportContent.tsx:11-29 | common/models/base/Faq.php:21-22 | done | Ours adds status/category/sort (superset) |
| 3 | FAQs listed as single-open accordion, first open by default | SupportContent.tsx:71-90 | backend/views/faq/index.php:82-153 | partial | Ours is a CRUD table + detail page, not an accordion read view |
| 4 | "Add FAQ" via modal (Question+Answer), success toast | SupportContent.tsx:108-130 | backend/controllers/FaqController.php:106-137 | partial | Ours = full-page create form + flash (modal flow retired) |
| 5 | Add disabled until both fields filled | SupportContent.tsx:117 | common/models/base/Faq.php:63 | done | Server-side required validation |
| 6 | FAQs "shown in customer & shop help centres" (public read) | SupportContent.tsx:64 | Faq.php status/category_id | partial | Ours has status/category to gate display; help-centre wiring not verified here |
| 7 | Contact Us tab: Email / Phone / WhatsApp channel cards | SupportContent.tsx:93-106 | — | missing | No admin contact-channel config screen. `ContactUsController` is an inbound-message inbox (different feature) |
| 8 | Contact values: support@navagoo.sa / +966 11 200 0000 / +966 55 000 0000 | SupportContent.tsx:95-105 | — | missing | Not surfaced anywhere as managed config |
| 9 | FAQ content is global (both customer + shop help centres) | SupportContent.tsx:64 | Faq.php (no shop_id) | done | Both treat FAQ as global platform content |
| 10 | No edit/delete/reorder/status in demo admin | SupportContent.tsx (none) | FaqController update/delete/change-sort:56-185 | done | Ours exceeds — full CRUD + drag-sort |
| 11 | No RBAC in demo | — | FaqController.php:18-36; QuestionsController.php:20-44 | done | Ours gates `manager` via checkPermissions; 403 vs redirect inconsistency across controllers |
| 12 | (NEW ours) Parallel ES-backed Questions entity | — | backend/controllers/QuestionsController.php; common/models/base/Questions.php | n/a | No demo counterpart |
| 13 | (NEW ours) Technical Support ticket flow (shop→admin) | — | frontend/controllers/TechnicalSupportController.php; backend/controllers/TechnicalSupportController.php | n/a | Outside demo scope |
| 14 | (NEW ours) Inbound Contact-Us message inbox | — | backend/models/ContactUs.php:17-25 | n/a | Inverse of demo's channel display |

## Scoring rationale
The demo screen has 2 capabilities: **FAQ management** and **Contact-channel display**.
- FAQ management: ours is a functional superset (persistence, validation, CRUD) but diverges
  in UX (table vs accordion, full-page form vs modal, no unified screen). ~ strong-partial.
- Contact-channel display: entirely missing on our side (our same-named controller is a
  different inbox feature).

Counting the 11 demo-derived rows (excluding NEW-ours rows 12-14): done=5, partial=3, missing=3.

**Area score: 55%**

## Verified verdict (adversarial)

Re-read both sides line-by-line. Findings below downgrade two claims; the rest hold.

| # | Demo behavior | Analyst | Verified | Evidence |
|---|---|---|---|---|
| 2 | FAQ = `{question, answer}` | done | **done** | `common/models/base/Faq.php:60-67` requires question+answer; superset cols are additive. Note: `FaqController::actionCreate` hardcodes `category_id = 1` (`backend/controllers/FaqController.php:117`), so category is not user-chosen on create — cosmetic, shape still matches. |
| 5 | Add disabled until both fields filled | done | **done** | Server `[[question,answer],required]` (`Faq.php:63`) + ActiveForm client validation (`backend/views/faq/_form.php:44`). UX differs (inline error vs disabled button) but the guarantee — cannot persist an empty FAQ — holds. |
| 6 | FAQs surfaced in help centres; status gates display | partial | **partial (refuted detail)** | "status/category gate display" is NOT implemented. No `Faq` reference anywhere in `frontend/` (customer/shop help centre is unwired). The only public surface is `api/controllers/FaqController.php:28` which does `FaqResource::find()->orderBy(sort)->all()` with **no `status` filter** — inactive FAQs are served to the app; `status` is merely echoed as a field (`api/resources/FaqResource.php:16`). So inactive-hiding is client-side at best, not enforced. |
| 9 | FAQ content is global (no shop scoping) | done | **done** | No `shop_id` on `faq` table; both sides global. |
| 10 | Edit/delete/reorder/status mgmt (ours exceeds) | done | **done** | `FaqController` 56-190 + `change-sort` demi action; index view exposes all. |
| 11 | RBAC / permission gating | done | **partial (downgraded)** | Gating is behaviorally inconsistent and partly unsound: `FaqController`/`QuestionsController` throw **403** on denial (`FaqController.php:30`, `QuestionsController.php:41`) while backend `TechnicalSupportController` **redirects to `/`** (`TechnicalSupportController.php:30`). Worse, `FaqController::beforeAction` (18-36) never calls `parent::beforeAction`, and on a user with no roles `current($roles)` is `false` → `$role->name` comparison is falsy → falls through to `else { return true; }`, **granting access**. `QuestionsController` (39) guards with `if ($role && ...)` but reaches the same permissive `return true` for non-managers. Not a clean RBAC match. |

Items 1, 7, 8 (missing) and 3, 4 (partial) confirmed as graded: separate `/faq` + `/contact-us` menu items (`backend/views/layouts/menu/Menu.php:165,173`), no segmented tab; `backend/models/ContactUs.php` is an inbound-message inbox (required `title/message/type`), not a managed Email/Phone/WhatsApp channel-config screen — no such config exists in `backend/`/`common/`.

### Adjusted scoring
Re-grade of the 11 demo rows: row 11 RBAC done→partial. New tally: done=4, partial=4, missing=3.
Weighting done=1.0, partial=0.5, missing=0 over 11 rows → (4 + 2.0) / 11 = **54.5% → 54%**. The 55%
headline was marginally optimistic; the RBAC "done" was the main overclaim (gating is inconsistent
and fail-open for role-less users), and the item-6 "status gates display" detail is unsupported by
the actual public read path.

**Adjusted area score: 54%**
