# WBMCZ — deploy notes · 06 Sep 2026 (seventh pass)
## The permission ticks now actually do something

No database change. Four files.

    includes/acl.php                    the registry, brought up to date
    includes/pipeline.php               a role can carry a desk, not just a person
    admin/includes/user_list_engine.php the ticks are enforced — this is the big one
    admin/index.php                     the dashboard blocks answer to their own keys

Upload `includes/` first, then `admin/`.

---

## 1 · THE BUG UNDER THE WHOLE THING

`users.delete`, `users.password`, `users.wallet` and the rest have been tickable
on the Roles screen for a long time. **Nothing on the user list ever asked.**

So "do not let them delete users" was a tick that changed nothing: the Delete
button was drawn for everybody, and the POST behind it ran for everybody. You
were setting access that was never read.

Every one of them is now asked **twice** — once to decide whether to draw the
button, and once at the top of the handler behind it. The second is the one that
matters: a button that is not drawn can still be posted by hand, and the answer
to that has to be no.

| Tick | Hides | Refuses |
|---|---|---|
| `users.create` | — | Add user |
| `users.edit` | Edit Details, Make Customer, Make Seller | the same, and role changes |
| `users.delete` | Delete, bulk Delete | both |
| `users.restore` | Restore | Restore |
| `users.block` | Activate, Suspend | both, and the row toggle |
| `users.password` | **Reset Password** | Reset Password |
| `users.wallet` | the whole **Transfer** column | credit, debit, transfer |
| `users.kyc` | KYC button greys out with a reason | approve / reject / edit |
| `users.note` | New Notes | writing a note |
| `users.upgrade` | Subscribe, Unsubscribe | both |
| `users.export` | Export CSV **and** Export N selected | the export URL |

The bulk bar was the awkward one: one bar, several different powers behind it. So
the key is chosen by **which button was pressed**, not by the bar as a whole —
somebody who may suspend but not delete gets Suspend and no Delete.

---

## 2 · THE REGISTRY NOW MATCHES THE PANEL

**389 keys across 20 modules**, and they describe the panel as it is today rather
than as it was three passes ago.

### Dashboard — one key per block

    dashboard.col.waiting   Waiting for somebody (the queue tiles)
    dashboard.col.earning   Money — income, expenses, company income
    dashboard.col.orders    Orders — total, completed, in progress
    dashboard.col.users     People — members, sellers, referrals, staff
    dashboard.col.wallet    Wallets — held, bonus, seller cash & dues
    dashboard.col.charts    Where the money comes from
    dashboard.col.recent    Latest orders

Each block is drawn only if its key is held. Give somebody orders but not money
and they get the order block, not an empty money row. An account that can open
the dashboard but holds none of the blocks gets one line saying so.

### Activity & Task — one key per desk, 25 of them

    tasks.tab_lead              User · Lead
    tasks.tab_kyc_pending       User · KYC Pending Request
    tasks.tab_s_lead            Seller · Lead
    tasks.tab_product_request   Seller · Product Requests
    tasks.tab_visit_collect     Office · Visit Collection
    tasks.tab_verify_collect    Office · Verify Collection
    tasks.tab_seller_dues       Office · Seller Dues
    …and eighteen more

User and Seller both have a Lead desk and a KYC desk, so **the side is in the
name** — otherwise the Roles screen shows the same words twice and you cannot
tell which one you are ticking.

**This does not replace the per-person list.** The board already lets you pick
desks for one person when you hand work over. These keys sit alongside it so a
**role** can carry the same thing — give the role "Verify Collection" and
everyone in it has that desk without setting each person up by hand. Whichever
says yes wins; neither takes anything away from the other.

Also new: `tasks.access` — may this person hand out board access to others.

### The rest, refreshed

Seller Management, per-category Product Management, the four user list pages —
all of them are on the Roles screen with their own keys.

---

## 3 · AN ADMIN CREATING STAFF — ALREADY BUILT, HERE IS THE SWITCH

This one needs no code. It is a tick you have not turned on yet.

An admin can create employees the moment they hold **Staff & Roles → Create an
employee** (`staff.create_employee`). Right now:

    #31    Super Admin      superadmin   can create: Admin, Employee   ceiling 389 keys
    #1340  tech sujit       admin        can create: nobody            ceiling 87 keys

Give `tech sujit` that one tick and "Employee" appears on their Add Staff screen.
They will also want **Staff & Roles → See staff accounts** to reach the page, and
**Give or take back access** to fine-tune what they hand over.

### And they can never give away more than they hold

This is already enforced, in two places, and it is worth knowing it is not a
convention — it is a filter on the way in.

* **The ceiling.** Every grant is passed through `acl_filter_grant()`, which
  keeps only keys the giver actually holds. `tech sujit` holds 87 keys, so 87 is
  the most an employee they create can ever be given — the other 302 are dropped
  on save, not merely hidden in the form.
* **Who they can touch.** An admin manages employees only. Never another admin,
  and never themselves out of existence.

A super admin has `*`, so their ceiling is all 389.

---

## 4 · CHECKED

* all four files pass `php -l`
* 68 admin pages load with no fatal, no warning and no notice
* 389 keys across 20 modules, and `acl_all_keys()` agrees with the count
* every user-management action has a handler guard; the buttons for edit,
  delete, restore, block, password, wallet, KYC, note, upgrade and export are
  hidden without their key
* the Transfer column is counted the same way it is drawn, so hiding it does not
  leave the empty-list row spanning one column too many
* the 25 desk keys all carry their side in the name

**Needs your eyes**, because it is behind the sign-in: make a role with, say,
User Management but *without* Delete and Reset Password, put a test employee in
it, sign in as them and check those two buttons are gone. Then tick
`staff.create_employee` on `tech sujit` and confirm Add Staff offers Employee.
