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

Story vitest gate (motir-core) — the coverage floor, the rail↔page↔service key agreement, and the guards that keep hiding from becoming enforcement

The story's per-repo coverage and integration gate. It runs after the feature subtasks merge, because it measures their real merged surface, and it does three things — none of which is a static list of cases decided in advance.

1 · Coverage floor. Run coverage over the surface this story changed — the provider, the layout's access read, the settings registry, the nav-permission map, SidebarNav, AppCommandPalette, every app/(authed)/settings/project/**/page.tsx — and wherever a file sits below the project's per-file floor, write the missing unit and branch tests to reach it. "Already covered by the subtask's own tests" is the expected normal here, not a reason the card has nothing to do; this tops up the seams BETWEEN the subtasks.

2 · Integration seams — the ones no single card can assert. Real Postgres, real services, no mocked policy:

  • The three-way key agreement. For every settings entry, the key the RAIL hides on, the key the destination PAGE refuses on, and the key that page's own SERVICE asserts must be the same key. Each sibling card asserts its own half; nothing today compares all three, and a disagreement between any two is invisible — every surface renders, every surface refuses, and the only symptom is the wrong people admitted or excluded.
  • Resolution to render, end to end. Seed a real actor at each built-in role, resolve their permissions through projectAccessService.getPermissionsDTO, feed that DTO to the shell's filters, and assert the visible rail, project nav, palette entries and settings-area door — the whole path from a database row to a rendered set, which the unit tests each mock one end of.
  • The partial-administrative-domain case, at the level where it is assertable today. No built-in role holds one administrative key without the other eleven, so the parent story deferred the live walkthrough to the custom-roles story. Assert it here over a synthetic set: {project:browse, board:configure} yields Board in the rail, omits Members, and is refused at /settings/project/members.

3 · Architecture and contract guards — the things coverage cannot see.

  • Hiding never became enforcement, and enforcement never got weaker. The set of assertPermission / assertCan* call sites under lib/services/** and app/api/** is unchanged by this story: a guard test pins it, so a future card cannot quietly move a gate into the presentation layer or drop one on the way past.
  • No second gating list. A structural guard asserts the settings rail, the palette's settings block, the project nav and the palette's nav entries all resolve through their registry / map, with no independent copy.
  • No legacy boolean survives. A repo-wide guard asserts nothing reads canEdit or canManage from the project-access context.
  • Tenancy. An actor's resolved set on a project in another workspace is empty and the surfaces render nothing — the cross-tenant arm, on real Postgres with RLS in force.

Scope boundary

In: tests and test helpers in motir-core, plus whatever minimal production change a guard proves necessary. Out: every other repo — this gate never straddles; and any new feature behaviour, which belongs to the card that owns the surface.

Acceptance criteria

  • Every file this story changed meets the project's per-file coverage floor; the PR body records the before/after for each file that needed topping up.
  • A test asserts, for every entry in the settings registry, that the rail's key, the destination page's key and that page's service gate name the same permission — and it is TOTAL over the registry, so a new entry joins the assertion automatically.
  • An integration test drives the full path for each built-in role — seeded membership → resolved DTO → rendered rail, nav, palette and area door — against real Postgres.
  • The synthetic partial-domain case is asserted: Board visible, Members hidden, /settings/project/members refused.
  • A guard pins the server-side gate call sites so this story provably neither added nor removed enforcement.
  • Guards assert: no second gating list for any of the four gated surfaces; no reader of canEdit / canManage from the project-access context anywhere in the repo.
  • The cross-tenant arm is covered on real Postgres, not a mock.
  • The suite runs in CI as part of the standard test job and adds no new external dependency.

Context refs

  • tests/permissions/getPermissions.integration.test.ts, tests/permissions/accessParity.test.ts, tests/permissions/rolesStoryGate.integration.test.ts — the shipped permission suites this gate extends rather than duplicates.
  • tests/settings/projectSettingsNav.test.ts — the filesystem-enumerating totality guard whose technique the three-way agreement test reuses.
  • lib/services/projectAccessService.tsgetPermissionsDTO and assertPermission, the two ends of the path under test.
  • The client-set card, the registry card, the destination-guard card, the nav-and-palette card, the affordance sweep — the five deliverables whose merged surface this gate measures.