# WP7 — The remaining resources, and closing the feature honestly

**Repo:** BE + FE · **Branch:** `hazemdev2` · **Migration:** likely · **Depends on WP6** · **Last WP**

## Goal

Extend the mechanism to the resources the analysis identified but did not prioritise, **and** close
out the loose ends the earlier WPs deliberately left.

By now the pattern has been proven twice (warehouses, cash boxes). This WP should be mostly
mechanical — **if it isn't, that is a finding worth reporting rather than forcing.**

## Part 1 — the remaining resources

| Resource | Today | Note |
|---|---|---|
| **POS terminals** | `branch_id` exists; **no user link**; the session-open dialog fetches terminals raw and requires a manual choice | A cashier bound to one terminal should not pick it every shift |
| **POS sessions** | `user_id` exists, but `index` filters by a **request-supplied** `user_id` — any POS user can list everyone's sessions | The data is there; the enforcement is not |
| **Cost centres** | **no user link, no branch column** — company-scoped only | The only resource with *no* scoping axis at all |

**Judge each before building it:**
- POS sessions look like the highest value/lowest cost — the column exists, only enforcement is missing.
- Cost centres have **no axis to scope by**. Adding a pivot is possible, but ask whether anyone
  actually needs per-user cost-centre visibility, or whether this is completeness for its own sake.
  **A clear "not worth it, and here's why" is a perfectly good outcome** — record it as a deferral
  rather than building an unused table.

## Part 2 — close the loose ends

1. **The legacy columns.** `warehouses.manager_id` and `petty_cash.custodian_id` were migrated into
   the pivots (WP1) and left in place. Now that assignments are real and reviewed, decide their fate:
   drop them, or keep them as a display-only "primary contact" with a comment saying they no longer
   restrict anything. **Do not leave them ambiguous** — an unmarked dead column that once looked like
   security is exactly what started this whole feature.
2. **Verify the invariant test covers every wired module** (Inventory, Accounting, plus whatever this
   WP wires) and that its exemption allow-list still reads correctly, each entry with its reason.
3. **Sweep for any remaining client-side row filtering** across the whole app. WP4 removed the
   warehouse ones and WP6 the cash ones. If any survive, list them — every one is a place where data
   reaches the browser and is merely hidden.

## Acceptance criteria

1. Each remaining resource is either wired end-to-end, or explicitly deferred with a written reason.
2. POS session listing is enforced server-side rather than by a client-supplied `user_id`.
3. The legacy columns' status is unambiguous — dropped, or documented as non-restricting.
4. The invariant test covers every module this feature touched and is green.
5. No client-side row filtering remains anywhere, or the survivors are listed.
6. Relevant module suites: **zero NEW failures**.
7. `npx ng build --base-href /app/` green; `npx tsc --noEmit` clean.

## Environment / rules

- Tests: `cd /home/moonui2/moon-erp-be && /opt/cpanel/ea-php82/root/usr/bin/php -d memory_limit=1G vendor/bin/pest --filter='…'`
  (bare `php` is php-cgi → "Undefined constant STDOUT").
- ⛔ **Pest loads every test file into ONE process** — prefix every top-level helper with its file's
  subject. Duplicate top-level function = fatal redeclare, exit 255, zero output (5 occurrences here).
- ⛔ NEVER `migrate:fresh` / `migrate:refresh` / `db:wipe` on `moonui2_dev_be` — not binlogged.
- ⛔ **NEVER** `git checkout` / `restore` / `stash` on `src/assets/i18n/ar.json` or `en.json`.
- API auth header is `X-Authorization: Bearer`.
- `./vendor/bin/pint` on touched files only. `chown moonui2:moonui2` every edited file.
  `bash local-deploy.sh` after BE edits. Builds pre-authorized; **do NOT deploy to `/app`**.
- Bilingual `[Unreleased]` bullet for anything user-visible.
- Commit on `hazemdev2`, conventional. **Do not push, do not merge.**
- moonui2 ONLY — never `/home/moonui`. Never print a git remote URL.

## Out of scope

Building a scoping axis for a resource nobody asked to scope — say so instead.
