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

Retire `repository:connect` — the provider connection binds an installation to a WORKSPACE, so no project permission can govern it

The inventory maps six operations to repository:connect under reason R7, "connects a provider installation and triggers indexing". Read on origin/main, all six turn out to have no project in them at all:

OperationWhat it resolves
/api/github/oauth/start · /api/github/oauth/callbackgetSession(); redirects to /settings/workspace/github
/api/github/setupgetSession() + workspacesService; binds the installation to a WORKSPACE
/api/github/organizationsgetWorkspaceContext()
/api/gitlab/oauth/start · /api/gitlab/oauth/callbackgetSession() + getWorkspaceContext(); the file's own header says "WORKSPACE-scoped, so we resolve the acting member's active workspace"

A project permission cannot gate an operation that never names a project. And the catalog's opening rule is explicit that a key exists because there is an operation it governs — "letting a user invent one would put a switch on a settings page that controls nothing" — so leaving repository:connect in place to be rendered by the Roles & permissions page is precisely the lie the model was built to prevent. It goes.

This does not leave the repository domain empty or the concern ungoverned: attaching a repository row TO a project is /api/projects/[key]/repositories, which is repository:manage and is wired by its own card. The split matches both mirrors — Jira and Plane put the provider connection at the org/workspace level and repository linking at the project level.

No route behaviour changes here. The six keep exactly the session / workspace gates they have; this card removes a key that was never wired and records the correct answer for those rows.

Acceptance criteria

  • Confirm before removing. Open all six route files on the branch and confirm none resolves a project id (getActiveProject, a [key] param, or a projectsService.getByKey). If ANY of them does, STOP and record what you found on this card instead of forcing the retirement — the finding is worth more than the edit.
  • repository:connect is removed from PERMISSIONS and PERMISSION_META in lib/permissions/catalog.ts. The repository domain still holds repository:manage and repository:manage_access, so the no-empty-domain guard is satisfied.
  • messages/en.json and messages/zh.json drop permissions.repository_connect.label / .description in the same change — the catalog guard asserts both catalogs are TOTAL over the key set, and an orphaned pair is dead copy in two locales.
  • The six rows in docs/decisions/permission-inventory.md's repository section become decision workspace-scoped with permission , citing R3 (the workspace/org administration reason). Their gate-today cells record what was actually read. If no row cites R7 afterwards, delete R7 rather than leaving a reason nothing points at.
  • The catalog's own count sentence and the inventory's "The resulting catalog" table are updated to 31 keys, and the repository (3) row becomes repository (2).
  • The guard's pending pin falls by exactly these six operations — re-derived by running tests/permissions/noUngovernedOperation.test.ts on the branch, not copied from here, since the guard-repair card moves the same number.
  • pnpm test green; pnpm lint and the prettier check pass repo-wide.

Context refs

  • app/api/github/oauth/start/route.ts · app/api/github/oauth/callback/route.ts · app/api/github/setup/route.ts · app/api/github/organizations/route.ts · app/api/gitlab/oauth/start/route.ts · app/api/gitlab/oauth/callback/route.ts — the six.
  • lib/permissions/catalog.tsPERMISSIONS, PERMISSION_META, the domain-non-empty guard, and the header rule this card applies.
  • docs/decisions/permission-inventory.md — the repository section, the Reasons list (R3, R7), and the resulting-catalog table.
  • messages/en.json · messages/zh.json — the permissions.* namespace.
  • tests/permissions/catalog.test.ts — the duplicate-key, domain-non-empty and i18n-totality assertions.
  • The inventory that mapped them · the guard repair.