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-2347Done

DECISION — which built-in role holds each of the eight member-facing keys, and what a workspace member with no project membership keeps

The question. For each of the eight member-facing keys, which built-in role holds it — admin, member, viewer — and does the ACCESS LEVEL subtract it the way project:administer is subtracted, or does it need its own branch? Every answer takes a capability away from somebody who has it today, because the shipped answer for all eight is "anyone signed in". It is settled ONCE, here, against the mirrors and the shipped access model — never per-route while wiring, where each card would answer it alone and the eight answers would not agree.

The deliverable is docs/decisions/member-facing-permissions.md, in the shape of the existing records in docs/decisions/ — the question, the options considered, the decision per key with its evidence, and what it gates.

The recommendation this card records, and the evidence behind each row

Rung 1 is the mirror; rung 2 is this codebase. The recommendation is what the evidence supports, not what is least disruptive.

KeyRole setRung-1 evidenceWho loses what
sprint:manageadmin + memberPlane: Admin and Contributor create and manage cycles; Commenter and Guest cannot. Jira team-managed: Member. Jira company-managed makes Manage Sprints a SEPARATE permission typically held by Scrum Masters — narrowing it further is exactly what custom roles will allow, on top of this defaulta viewer loses starting, completing and re-ranking
report:viewadmin + member + viewerJira has NO separate report permission: Browse Projects is what governs reports and other aggregated reads. Plane's analytics follow project visibilitynobody who can browse; a non-member on a private project already cannot browse
saved_filter:manageadmin + membera saved filter is authored content with a star and a subscription — creating one is a write, and Jira treats filter creation as a logged-in user capability while sharing is separately governeda viewer loses authoring and subscribing, keeps reading results
import:runadmin onlyPlane: only workspace admins can perform imports, to maintain governance. Linear: you must be a Linear Admin to run an importa member loses running an import — the largest single revocation in this story
work_item:deleteadmin onlyJira's default permission scheme grants Delete Issues to the Administrators project rolea member loses archiving and the delete cascade, keeps editing every field
work_item:triageadmin + memberPlane: Admin and Contributor accept / decline / snooze an intake item; Guest and Commenter may only SUBMITa viewer loses accepting and declining, keeps reading the queue
ai:planadmin + memberMotir's own ai:configure already put the AI SETTINGS behind admin; the mirrors put AI configuration at admin and usage at member. A planning job spends the workspace's credits, so it is a write with a billa viewer loses running the planner
ai:view_planadmin + memberapproving a generated plan MATERIALIZES work items — it is a create, not a read, and Motir already gates the review surface's writes with assertCanEdita viewer loses approve / decline / proposal edit

The two structural sub-questions, which are the ones a per-route answer would get wrong

  1. The implicit workspace member. IMPLICIT_WORKSPACE_MEMBER_PERMISSIONS in lib/permissions/builtinRoles.ts is what a workspace member holds on a project they hold NO membership in — today project:browse, work_item:edit, comment:add, attachment:create. The recommendation is that it gains report:view and NOTHING else. A stranger to the project may read its charts because they may already read its work items; they may not spend the workspace's AI credits, run an importer, restructure a sprint or delete a subtree on a project nobody put them on. This is the one place ai:plan at member is not the whole answer, and it is invisible from any single route.
  2. levelGrants branches. lib/permissions/resolve.ts names only work_item:edit / comment:add / attachment:create; every other key takes the default arm, which is what made the administrative split provably behaviour-neutral. The recommendation is to add NO new branch. Each of the eight then behaves exactly as project:administer does per level — kept on open / public, kept on limited, and on private gated on project membership alone — and the whole capability question stays in the ROLE sets, where it is readable in one place. A key that genuinely needs a per-level rule would be a second policy axis, and the file says so in its own comment.

Acceptance criteria

  • docs/decisions/member-facing-permissions.md exists, follows the shape of a sibling record in docs/decisions/, and states for EACH of the eight keys: the decision, the mirror evidence with its source, and the capability that is revoked on the day it lands.
  • It answers both structural sub-questions explicitly — the implicit-workspace-member set, and whether levelGrants gains a branch — with the reasoning, not just the verdict.
  • It names, per key, the actor who can no longer perform the operation, so the revocation list can be read without opening any other file.
  • It records the ONE loosening in the story (/api/ai/coding-convention/*, admin-gated today and mapped to ai:plan) as a decision in its own right: either the inventory mapping is corrected or the widening is intended, and the document says which and why.
  • Every claim about the shipped model cites the file it was read from on origin/mainlib/permissions/builtinRoles.ts, lib/permissions/resolve.ts, lib/services/projectAccessService.ts — and no claim about a mirror is made without its source link.
  • The record names the cards it gates, so a reader arriving at it from a wiring card can see what it decided for them.

Context refs