tenseleyflow/shithub / 3b4356e

Browse files

docs/api: search reference page

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
3b4356ea8ad2e9ee8793bfc4b4bc9896d772199f
Parents
d9baee5
Tree
d38747c

1 changed file

StatusFile+-
M docs/public/api/search.md 112 26
docs/public/api/search.mdmodified
@@ -1,43 +1,129 @@
11
 # Search
22
 
3
-> **Planned.** Search over the API is not shipped yet. The web UI's
4
-> `/search` is the only entry point today.
3
+Per-type search over shithub's Postgres FTS corpus. Every result
4
+set is filtered by the caller's visibility — anonymous callers
5
+see only public rows.
56
 
6
-## Planned routes
7
+## Response shape
78
 
8
-| Method | Path                              | Scope                          |
9
-|--------|-----------------------------------|--------------------------------|
10
-| GET    | `/api/v1/search/code`             | None (public corpus only without `repo:read`); `repo:read` to include private. |
11
-| GET    | `/api/v1/search/repositories`     | Same scoping.                  |
12
-| GET    | `/api/v1/search/issues`           | Same scoping.                  |
13
-| GET    | `/api/v1/search/users`            | None.                          |
9
+Every endpoint returns the canonical gh-compatible envelope:
1410
 
15
-Query parameters:
11
+```json
12
+{
13
+  "total_count": 142,
14
+  "incomplete_results": false,
15
+  "items": [
16
+    { /* type-dependent record */ }
17
+  ]
18
+}
19
+```
20
+
21
+`incomplete_results` is always `false` in v1 (the FTS pipeline
22
+runs to completion before responding). The field is preserved on
23
+the wire so future ranker timeouts can flip it.
24
+
25
+`total_count` is the unbounded result count.
1626
 
17
-- `q=` — search query, with the same operators as
18
-  [Search (user docs)](../user/search.md).
19
-- `sort=` — `created`, `updated`, `stars`, `relevance` (default).
20
-- `order=` — `asc`, `desc`.
21
-- `per_page=`, `cursor=`.
27
+## Query syntax
2228
 
23
-Response shape (proposed):
29
+The `q=` parameter is parsed by `internal/search/query_parse` —
30
+free-text terms plus the following operators:
31
+
32
+- `repo:owner/name` — restrict to one repo
33
+- `is:open` / `is:closed` (or `state:open` / `state:closed`)
34
+- `author:username`
35
+- `"quoted phrase"` — phrase search (one phrase per query)
36
+
37
+Unknown prefixes (e.g. `language:Go`) fall through as free text
38
+so future operator additions don't break older queries.
39
+
40
+## Search repositories
41
+
42
+```
43
+GET /api/v1/search/repositories?q=...&page=N&per_page=M
44
+```
45
+
46
+Scope: `repo:read` for authenticated callers; anonymous callers
47
+fall through to the public-only filter.
2448
 
2549
 ```json
2650
 {
27
-  "total_count": 142,
51
+  "total_count": 1,
52
+  "incomplete_results": false,
2853
   "items": [
29
-    { /* type-dependent record */ }
54
+    {
55
+      "id": 12,
56
+      "name": "demo",
57
+      "full_name": "alice/demo",
58
+      "owner_login": "alice",
59
+      "description": "demo repo",
60
+      "visibility": "public",
61
+      "private": false,
62
+      "star_count": 0,
63
+      "updated_at": "2026-05-12T05:00:00Z",
64
+      "score": 0.42
65
+    }
3066
   ]
3167
 }
3268
 ```
3369
 
34
-The total is **counted to a cap** (10000) — for larger result
35
-sets the API returns "10000+" semantics rather than counting
36
-exactly. Consumers that need totals should narrow the query.
70
+## Search issues
71
+
72
+```
73
+GET /api/v1/search/issues?q=...&type=issue|pr
74
+```
75
+
76
+Scope: `repo:read`. `type=issue` or `type=pr` narrows to one
77
+kind; omit to return both (issues share their table with PRs).
78
+
79
+```json
80
+{
81
+  "id": 17,
82
+  "number": 1,
83
+  "repo_id": 12,
84
+  "repo": "alice/demo",
85
+  "title": "needle in haystack",
86
+  "state": "open",
87
+  "kind": "issue",
88
+  "author_name": "alice",
89
+  "updated_at": "2026-05-12T05:00:00Z",
90
+  "score": 0.81
91
+}
92
+```
93
+
94
+## Search code
95
+
96
+```
97
+GET /api/v1/search/code?q=...
98
+```
99
+
100
+Scope: `repo:read`. Matches against the path-and-content index
101
+populated by the push pipeline. `preview_line` carries a single
102
+line of context for content hits; path-only hits omit it.
103
+
104
+```json
105
+{
106
+  "repo_id": 12,
107
+  "repo": "alice/demo",
108
+  "ref": "trunk",
109
+  "path": "internal/foo/foo.go",
110
+  "preview_line": "func Foo() error { return errors.New(\"foo\") }",
111
+  "score": 0.55
112
+}
113
+```
114
+
115
+## Pagination
116
+
117
+`?per_page=` (≤100, default 30) and `?page=` are supported, with
118
+the standard `Link:` header (see [overview](overview.md)). The
119
+`total_count` field is independent of the page slice — it counts
120
+all matching rows regardless of pagination.
37121
 
38
-## Visibility
122
+## Not yet shipped
39123
 
40
-Search results are filtered by the requesting PAT's user's
41
-visibility, identical to the web UI's behavior. A token cannot
42
-see a result it would not see in a browser logged in as the
43
-same user.
124
+- `GET /api/v1/search/commits` — commit message search; requires a
125
+  per-repo commit FTS index that doesn't exist yet.
126
+- `GET /api/v1/search/users` — backing query exists; REST surface
127
+  pending; will land alongside §7 orgs/users follow-up.
128
+- `sort=` / `order=` — every endpoint currently sorts by FTS rank;
129
+  exposing alternative sorts (created, updated, stars) is queued.