# POS Frontend — Continuation Branch: `authz-audit-2026-08-25` ## Session 2026-08-26d — Frontend Production Audit Stack: Go backend :8080, POS :5175 (Vite 8), Postgres km-pg, Redis km-redis. CORS `http://localhost:5175` + vite proxy `/api,/uploads → localhost:8080`. ### Fixed - **P0** `src/utils/permissions.test.js` fail-open → fail-closed — `can(undefined,'hr.employees.create')` sekarang `false`, `auth.refresh()` heals via `GET /auth/me`. - **P0** DB `users.application_access` `erp → pos` untuk `cashier`, `kasir.*`, `owner.*` (6 rows) — sebelumnya `isPOS === pos|platform` memblokir semua kasir (DB hanya `admin=platform`, sisanya `erp`), `POST /pos` via `cashier@pos` sekarang 201. - **P0** `.env` + `.env.example` BOM `EF BB BF` stripped. - **P1** `src/components/pos/ReceiptPreview.vue` tax double-add — `taxAmount=0`, `grandTotal=total` (backend `total_amount` sudah include pajak). - **P1** `vite.config.js` proxy `/api,/uploads → localhost:8080`. - **P1** `.env.example` docs: `# origin only — do NOT append /api/v1 (http.js normalizePath adds it)`. - **P1** `src/utils/permissions.js` `can()` fail-closed + glob `.*` — kept. - **P2** `src/stores/app.js` tax `enabled:false` by default — receipt overstate hidden until enabled. ### Verification - `bun run build` 1.35s (387KB/104KB gzip) ✓ - `bun run test` 8/8 ✓ - Playwright `http://localhost:5175/login` title `Kasir POS`, `POST /pos` 201 via `cashier@pos`, browser `Access-Control-Allow-Origin http://localhost:5175` 204 preflight after backend `CORS_ORIGINS` fix. - DB `sales_orders` 40, `invoices` 17. ### Still open (P2) - `VITE_USE_MOCKS` dead — services fallback silen ke mock data saat backend down (mask 500 sebagai empty). Wire `import.meta.env.VITE_USE_MOCKS==='true'` atau hapus flag. - `src/services/api/products.js` fetch `per_page=1000` client-filter — push ke backend query saat katalog >1k SKU. - `vite.config.js` `preview.port` vs `Dockerfile` `8080` intentional — document.