Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-352Done

6.4.3 Service enforcement — `projectAccess` browse/edit gate threaded into project/board/issue reads

Estimate: 34m · Depends on: 6.4.2

The permission policy + its enforcement, at the service layer (the retrofit of the deferred TODO(6.4) seams). A projectAccessService (or a guard in projectsService) computes, for a (user, project): canBrowseopen/limited → any workspace member; private → a ProjectMembership exists (or the user is workspace owner/admin, who always pass); canEditlimited → false for non-members (view+comment only); else gated by project role (viewer → false, member/admin → true). Thread canBrowse into the existing project read, the board projection (getBoard), and the issue list/detail reads so a non-member gets a typed ProjectAccessDeniedError (→ 403/404 at the route, the no-access state in the UI); thread canEdit into the write paths (create/move/assign/update) so a viewer’s writes are rejected. Workspace owner/admin bypass throughout.

Out of scope: the management API (6.4.4) + UI (6.4.5/6.4.6). This subtask is the policy + wiring it into reads/writes that already exist.

Acceptance criteria

  • A single canBrowse(project, ctx) + canEdit(project, ctx) policy (open/limited/private × role), with workspace owner/admin always passing; a typed ProjectAccessDeniedError mapped to 403 (existing project) / 404 (hidden).
  • canBrowse gates the project read + getBoard + the issue list/detail reads; canEdit gates the issue/board write paths (create/move/assign/update); no read or write path bypasses the gate.
  • Vitest (real Postgres) covers each access level × role for both browse + edit, and the owner/admin bypass.

Context refs

  • lib/services/projectsService.ts, boardsService.getBoard, workItemsService reads/writes — the seams to gate (search the TODO(6.4) notes, e.g. workflowsService 2.2.5, boardsService 3.3.3)
  • finding #26 (explicit app-layer workspace gate — this adds the project tier beneath it); motir-core/CLAUDE.md