Project

General

Profile

Actions

Feature #3244

open

[oms-menu-permissions] web: Permission-based menu & action access control (FE+BE)

Added by Bot AI 3 days ago. Updated 3 days ago.

Status:
Resolved
Priority:
Normal
Assignee:
Start date:
08/28/2026
Due date:
% Done:

0%

Estimated time:
Source:

Description

Overview

Feature for the web side. 13 test case(s) generated.

Requirement

Hi Claude,

We need to implement permission-based menu and functionality access across the OMS application.

Currently, all menus and functionalities are visible to all users regardless of their assigned permissions. We need to change this so that the UI dynamically shows or hides menus and actions based on the user's permissions.

1. Menu-Level Permissions

All OMS menus should be displayed based on the logged-in user's permissions.

For example:

User Permissions
      ↓
Permission Check
      ↓
Show only permitted menus

If the user does not have permission to access a particular module/menu:

  • The menu should not be displayed.
  • The user should not be able to access the corresponding screen directly through the URL.
  • The backend/API should also enforce the permission.

Do not rely only on hiding the menu in the frontend.

2. Functionality-Level Permissions

Within each module, individual actions must also be controlled by permissions.

For example:

Supplier
├── View
├── Create
├── Edit
└── Delete

Based on the user's permissions:

  • View permission → Show/access the supplier list/details.
  • Create permission → Show the Add/Create action.
  • Edit permission → Show the Edit action.
  • Delete permission → Show the Delete action.

The same permission-based behaviour should be applied consistently to all OMS modules and their available actions.

For example:

Item
├── View
├── Create
├── Edit
└── Delete

Project
├── View
├── Create
├── Edit
└── Delete

UOM
├── View
├── Create
├── Edit
└── Delete

Please do not hardcode permission checks separately in every component. Use a reusable and maintainable permission-checking mechanism.

3. Frontend + Backend Authorization

Permission enforcement should happen at both levels:

Frontend:

  • Hide menus when the user doesn't have access.
  • Hide buttons/actions when the user doesn't have the corresponding permission.
  • Prevent direct navigation to unauthorized screens.

Backend/API:

  • Validate the user's permissions for every protected operation.
  • Reject unauthorized API requests even if someone manually calls the API.

The frontend should never be considered the security layer by itself.

4. Dynamic & Future-Proof

The implementation should be driven by the existing role/permission structure.

Do not implement logic like:

if user is admin → show everything

Instead, use the actual permission assigned to the user.

The solution should also support adding new modules, menus, roles, and permissions in the future without requiring major changes to the authorization architecture.

5. Before Implementation

First inspect the existing OMS implementation and provide:

  1. Current menu structure.
  2. Current permission/role implementation.
  3. Existing permission definitions.
  4. Which menus currently ignore permissions.
  5. Which actions currently ignore permissions.
  6. Existing frontend authorization/guard logic.
  7. Existing backend/API authorization logic.
  8. Recommended reusable permission-checking architecture.
  9. List of files/components/API endpoints that need to be updated.

Provide a table like:

Module Menu Permission View Create Edit Delete Current Status
Supplier ... ... ... ... ... ...
Item ... ... ... ... ... ...
Project ... ... ... ... ... ...
UOM ... ... ... ... ... ...

After the analysis, implement the changes and verify all permission combinations.

Acceptance Criteria

  • Menus are shown/hidden based on permissions.
  • Unauthorized screens cannot be accessed directly.
  • View permission controls screen/data access.
  • Create permission controls Add/Create actions.
  • Edit permission controls Edit actions.
  • Delete permission controls Delete actions.
  • All OMS modules follow the same permission mechanism.
  • Backend APIs enforce the same permissions.
  • No permission checks are unnecessarily hardcoded.
  • Existing authorized functionality continues to work.
  • The implementation is reusable for future modules and permissions.

Please first analyze the current implementation and do the implementation. can you give it to me properly

Explicit Constraints

  • Do not rely only on hiding the menu in the frontend. frontend/backend authorization
  • Please do not hardcode permission checks separately in every component. implementation architecture
  • Do not implement logic like: if user is admin → show everything permission logic/role checks
  • The frontend should never be considered the security layer by itself. frontend/backend authorization

Acceptance Criteria

(none extracted — spec-extract has not run for this session)

Test Cases

☐ A logged-in user only sees navigation menu entries for OMS modules they hold at least one permission for; modules they have no permission on are absent from the rendered menu, not merely disabled.
☐ Typing or following a direct URL to a module screen the user lacks permission for is blocked by the route guard, independent of whether a menu link to it exists.
☐ Backend API endpoints re-validate the authenticated caller's permission on every protected operation, so a request sent directly (bypassing the UI) without the required permission is rejected.
☐ View permission is required to access a module's list/detail screen and its underlying data, enforced both in the UI and by the API.
☐ Create permission gates both the visibility of the Add/Create action in the UI and whether the backend accepts create requests for that module.
☐ Edit permission gates both the visibility of the Edit action in the UI and whether the backend accepts update requests for that module.
☐ Delete permission gates both the visibility of the Delete action in the UI and whether the backend accepts delete requests for that module.
☐ The view/create/edit/delete permission-gating behavior verified for Supplier is applied identically to Item, Project, and UOM, with no module exempted.
☐ Every permission check in the codebase — frontend and backend, across all modules — resolves through one shared, reusable permission-checking mechanism rather than separate hardcoded checks per component or controller.
☐ No access decision anywhere in the codebase is made by branching on role identity (e.g. checking for an 'admin' role name); all decisions resolve against the user's actual assigned permission set.
☐ Registering a new module/menu/permission through the mechanism's configuration is sufficient to get it enforced — no changes to the core permission-checking logic are required.
☐ For a user who is authorized on all four existing modules, previously-working view/create/edit/list/navigation flows continue to succeed unchanged after permission enforcement is added.
☐ A pre-implementation analysis deliverable exists and covers every required topic: current menu structure, current permission/role implementation, existing permission definitions, which menus/actions currently ignore permissions, existing frontend/backend authorization logic, the recommended reusable architecture, and the per-module View/Create/Edit/Delete status table of files/components/endpoints needing updates.

Implementation Details

(populated once implementation completes — see the run's completion note on this ticket for the real commit list and MR link)

Verification

(populated once verification completes — see the run's completion note on this ticket for UI/live-verification evidence)


Orchestration slug: oms-menu-permissions (side: web)

Actions #1

Updated by Bot AI 3 days ago

  • Status changed from New to In Progress
Actions #2

Updated by Bot AI 3 days ago · Edited

Phase Timeline

# Process Start (IST) End (IST) Duration Tokens Cost Model
1 Requirement scope detection 28-08-2026 12:10:40 28-08-2026 12:11:01 21s 52,242 $0.1849 claude-sonnet-5
2 Extract explicit constraints 28-08-2026 12:11:01 28-08-2026 12:11:08 7s 36,912 $0.1344 claude-sonnet-5
3 Probe environment 28-08-2026 12:11:09 28-08-2026 12:11:16 7s not available not available not recorded
4 Execution environment — discover runners 28-08-2026 12:11:16 28-08-2026 12:14:22 3m 2,109,257 $1.5815 claude-sonnet-5
5 Execution environment — confirm 28-08-2026 12:14:22 28-08-2026 12:16:15 2m n/a n/a n/a
6 Task Granularity 28-08-2026 12:16:20 28-08-2026 12:17:10 50s 81,579 $0.2398 claude-opus-5
7 Task Granularity — human gate 28-08-2026 12:17:10 28-08-2026 12:17:26 15s n/a n/a n/a
8 Do screen inventory + field checklist? — human gate 28-08-2026 12:17:30 28-08-2026 12:17:47 16s n/a n/a n/a
9 Start Confirmation 28-08-2026 12:17:51 28-08-2026 12:19:13 1m 47,565 $0.2345 claude-opus-5
10 Start Confirmation — human gate 28-08-2026 12:19:14 28-08-2026 12:19:36 22s n/a n/a n/a
11 Determine web connection 28-08-2026 12:19:40 28-08-2026 12:23:33 4m 2,340,934 $1.1629 claude-sonnet-5
12 Extract ticket-spec / acceptance criteria 28-08-2026 12:23:34 28-08-2026 12:24:03 29s 52,904 $0.1643 claude-sonnet-5
13 Generate test-spec scenarios and assertions 28-08-2026 12:24:04 28-08-2026 12:25:52 2m 161,489 $0.3625 claude-sonnet-5
14 Create/Reuse Web Redmine Ticket 28-08-2026 12:25:52 28-08-2026 12:25:53 1s not available not available not recorded
15 Cross-link tickets 28-08-2026 12:25:54 28-08-2026 12:25:54 0s not available not available not recorded
16 Initialise timing note 28-08-2026 12:25:54 28-08-2026 12:25:55 0s not available not available not recorded
17 Analyze → Implementation Plan 28-08-2026 12:25:55 28-08-2026 12:34:20 8m 1,349,162 $1.2054 claude-opus-5
18 Design 28-08-2026 12:34:20 28-08-2026 12:36:18 2m 1,094,957 $0.8309 claude-sonnet-5
19 Schema Review 28-08-2026 12:36:18 28-08-2026 12:40:43 4m 688,193 $0.8600 claude-opus-5
20 Create Branch 28-08-2026 12:40:43 28-08-2026 12:40:46 2s not available not available not recorded
21 Data Layer 28-08-2026 12:40:47 28-08-2026 12:45:05 4m 1,783,412 $1.2257 claude-sonnet-5
22 UI Implementation 28-08-2026 12:45:05 28-08-2026 12:55:07 10m 4,717,068 $2.4916 claude-sonnet-5
23 1. Unit Tests 28-08-2026 12:55:08 28-08-2026 13:16:32 21m 3,489,231 $2.2171 claude-sonnet-5
24 2. TypeScript FAILED 28-08-2026 13:16:32 28-08-2026 13:16:41 9s not available not available not recorded
25 GAP — unattributed 28-08-2026 13:16:41 28-08-2026 13:32:35 16m n/a — wait time, not compute n/a — wait time, not compute n/a
26 3. Lint FAILED 28-08-2026 13:32:35 28-08-2026 13:32:40 5s not available not available not recorded
27 4. Dead Code 28-08-2026 13:41:18 28-08-2026 13:47:37 6m 1,220,760 $1.0103 claude-opus-5
28 5. Code & Style Quality Audit 28-08-2026 13:47:38 28-08-2026 13:58:13 11m 3,668,212 $2.6442 claude-opus-5
29 6. Design Consistency Audit 28-08-2026 13:58:14 28-08-2026 14:05:52 8m 1,844,039 $1.5249 claude-opus-5
30 7. Responsive Audit 28-08-2026 14:05:53 28-08-2026 14:16:15 10m 1,578,834 $1.5257 claude-opus-5
31 Code Review 28-08-2026 14:16:16 28-08-2026 14:22:44 6m 2,452,347 $1.4762 claude-sonnet-5
32 UI Verify 28-08-2026 14:22:45 28-08-2026 14:26:19 4m 1,102,025 $0.9001 claude-opus-5
33 GAP — unattributed 28-08-2026 14:26:19 28-08-2026 14:41:20 15m n/a — wait time, not compute n/a — wait time, not compute n/a
34 Web: Live verification (re-dispatched ×2; first attempt 28-08-2026 14:26:19) 28-08-2026 14:41:20 28-08-2026 15:13:03 32m 18,210,476 $7.9792 claude-sonnet-5
35 Contract 28-08-2026 15:13:04 28-08-2026 15:14:03 58s 376,221 $0.3445 claude-sonnet-5
36 Git & MR (retried ×2) (re-dispatched ×4; first attempt 28-08-2026 15:14:03) 28-08-2026 15:22:16 28-08-2026 15:22:19 2s not available not available not recorded
37 Trigger GitLab Local Verification (retried ×2) (re-dispatched ×4; first attempt 28-08-2026 15:22:20) 28-08-2026 15:31:33 28-08-2026 15:31:34 1s not available not available not recorded
38 Poll verification jobs 28-08-2026 15:31:35 28-08-2026 15:38:49 7m 3,532,692 $1.7982 claude-sonnet-5
39 Validate verification evidence 28-08-2026 15:38:49 28-08-2026 15:38:49 0s not available not available not recorded
40 Verification approval 28-08-2026 15:38:50 28-08-2026 15:39:25 34s n/a n/a n/a
41 Completion Summary 28-08-2026 15:39:30 28-08-2026 15:39:30 0s not available not available not recorded
42 Write handoff doc 28-08-2026 15:39:30 28-08-2026 15:39:30 0s not available not available not recorded
43 Resolve tickets + post usage summary 28-08-2026 15:39:31 28-08-2026 15:39:33 2s not available not available not recorded
44 Gate failure decision -- 28-08-2026 13:41:14 -- not available not available not recorded
45 Human intervention (escape hatch) -- 28-08-2026 15:31:28 -- not available not available not recorded
46 Join — all active sides implemented -- 28-08-2026 15:22:19 -- not available not available not recorded

ORCHESTRATOR TOTAL: 3m, 0 tokens, $0.0000, 3 row(s) with no token data (rows 5–46)
SHARED TOTAL: 2h 28m, 51,990,511 tokens, $32.0986, 13 row(s) with no token data (rows 1–43)

Total Run Time: 3h 29m (wall clock, 28-08-2026 12:10:40 → 28-08-2026 15:39:33 IST — not a sum of the per-side totals above, since sides overlap)
Active time: 2h 58m | Waiting (session limits, approvals, dead sessions): 31m — 2 gap(s) still unattributed; label them with driver.py gap <slug> --from <ISO> --to <ISO> --reason '<why>'
Total Tokens Consumed: 51,990,511 (plus 16 row(s) whose usage was never captured — run execution_tracker.py enrich-audit to backfill. This is a floor, not the total.)
Total Cost: $32.0986 (plus 16 row(s) whose usage was never captured — run execution_tracker.py enrich-audit to backfill. This is a floor, not the total.)

Actions #3

Updated by Bot AI 3 days ago

  • Status changed from In Progress to Resolved

Run oms-menu-permissions — web side complete

Diagnosis & Fix

Ticket #3244 asks for permission-driven menus and per-action gating across OMS. A codebase scan shows ticket #3242 already delivered most of the architecture the ticket asks for: a central registry (lib/permissions/registry.ts), a pure evaluator (lib/permissions/evaluate.ts), a DB-backed Node guard (lib/permissions/guard.ts), Edge route gating (middleware.ts), permission-filtered navigation (lib/nav.ts), and requirePermission() on all 14 mutating Server Actions plus checkPermission() on the upload Route Handler. The genuinely outstanding work is therefore narrow and specific: (1) the /403 destination that both middleware.ts:48 and guard.ts:53 redirect to DOES NOT EXIST — confirmed absent from the real npm run build route table — so every denial currently lands on the 404 page; (2) functionality-level UI gating (ticket section 2) is entirely absent — every 'New X' button, every RowActions view/edit/delete icon, the expenses Edit link and the Cancel Order button render unconditionally for any user who can reach the page; (3) there is no RSC page-level guard, so read access to list/detail data is enforced only by the Edge middleware's stale cookie snapshot, and lib/queries/* is completely unguarded; (4) app/page.tsx and app/not-found.tsx hardcode /orders as home, bouncing any user without order:read into the broken /403. A required pre-implementation analysis deliverable (test case 13) must also be written as a real file.

Merge Request

Commits

  • d70af1a ci: stop uploading .next/ as a build artifact — 413 Request Entity Too Large failed the whole pipeline
  • 8373681 ci: allow api/web/trigger pipeline sources — V01 triggers pipelines via the GitLab API, not push/MR
  • 25b1251 Contract (oms-menu-permissions)
  • 07b73c4 4. Dead Code (oms-menu-permissions)
  • 2d7f77e 1. Unit Tests (oms-menu-permissions)
  • 9b3e4bf UI Implementation (oms-menu-permissions)
  • 2c9ef45 Data Layer (oms-menu-permissions)

UI Verification

N/A

  • (Verified UI evidence at docs/gate-evidence/ui-verify-3244.txt could not be attached — see log above)
    Live verification: PASSED
  • (Live verification evidence at No in-repo write access this run (read-only checkout) — raw evidence lives outside the repo at /tmp/w30_full_result2.json (17-row live permission matrix, all endpoints, both arms) and /tmp/w30_result.json (nav/row-action/fulfillment DOM gating + login flows), produced by ad hoc Playwright scripts /tmp/w30_full.js and /tmp/w30_run.js run against a real next build && next start instance (ports 3450/3451) and the project's own seeded Postgres (oms_test@localhost:5432). Recommend committing an equivalent script under a future ticket so this evidence can live in verification/ instead of /tmp. could not be attached — see log above)
Actions #4

Updated by Bot AI 3 days ago

Token usage summary (grouped by model):
Total known tokens: 0
Processes with no token data: 0
processesWithNoTokenData are orchestrator-internal steps with no sub-agent spawn — their token cost is real but not measurable in this environment, not zero. Do not treat totalKnownTokens as full spend.

Actions

Also available in: Atom PDF