MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-424

6.13.3 Search + category/tag filter over the public-projects directory (ride the shipped 6.1.1 FilterAST where it fits, else a scoped search)

Done
Description

Estimate: 50m · Depends on: 6.13.2

The search + category/tag narrowing over the 6.13.2 directory — the GitLab-Explore name-search + the GitHub-Topics / GitLab-Topics category filter. It NARROWS the same cursored directory read; it does NOT open a second query path.

  • Search: a name/description contains-match over the public projects in the directory. Ride the SHIPPED 6.1.1 FilterAST / its safe parameterized compiler + the trgm text index where it fits (the contains-match over project name/description is exactly its shape); where the project-level directory search does not map onto the 6.1.1 work-item search, a SCOPED parameterized search (no string-built SQL — the 6.1.1 injection-safety posture) over the public-project set. The search composes with the active rank tab (6.13.4) + the cursor pagination, and is bounded (no load-all of the result).
  • Category / tag filter: narrow the directory to a category/tag (the 6.13.5 tag model) — an EXISTS-over-the-tag-join predicate that composes with search + the rank under the cursor. (6.13.5 owns the tag model + the tag-facet read; this card consumes them as a filter predicate over the directory.) The tag filter + search are both parameterized, both respect the access_level = public directory filter (you can only ever search/filter public projects).

Stay 4-layer: the route parses the query/tag params + calls ONE service method that threads the search/tag predicate into the 6.13.2 cursored read; the predicate compilation lives in the service/repository (no raw Prisma in the route); no user string reaches SQL unparameterized.

Acceptance criteria

  • A name/description query narrows the directory to matching public projects; it rides the 6.1.1 FilterAST/compiler where it fits, else a scoped parameterized search — no string-built SQL on the path (injection-safe, the 6.1.1 posture).
  • A category/tag selection narrows the directory to that topic (an EXISTS over the 6.13.5 tag join); search + tag + the rank tab COMPOSE under one cursored read.
  • Both predicates respect the access_level = public directory filter (no non-public project is ever searchable/filterable) and the cursor pagination (no load-all of the result set).
  • 4-layer respected; no raw Prisma in the route; the search/filter compose with 6.13.2’s deterministic order + cursor.

Context refs

  • 6.13.2 (the cursored directory read this narrows) + 6.13.5 (the tag model the category filter consumes) + 6.13.4 (the rank the search composes with).
  • scripts/plan-seed/data/story-6.1.ts § 6.1.1 (the SHIPPED FilterAST + the safe parameterized compiler + the trgm text index this rides where it fits) — lib/filters/ast.ts / lib/filters/registry.ts.
  • GitLab Explore name search + Topic filter (https://gitlab.com/explore/projects/trending, https://docs.gitlab.com/user/project/project_topics/) — the search + category browse mirrored.
  • motir-core/CLAUDE.md § 4-layer + the repo-owns-$queryRaw rule.