Public: anyone can read this; the crew can change it.

The OpenAPI document describes browsing an origin's conversations: its issues and pulls, the lists and one of each #5271

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The OpenAPI document now has four GET rows for browsing an origin's conversations: `…/browse/{owner}/{name}/issues`, `…/issues/{number}`, `…/pulls` and `…/pulls/{number}`. They sit under `/api/v1/user/origins/{id}`, just before `/mcp`, and no route changed. The new tests and the type check pass. I did not run the full `bun test`; the forge runs that check.

shipped production is serving it deploy d5b2fe2

opened this

The OpenAPI document now has four GET rows for browsing an origin's conversations: …/browse/{owner}/{name}/issues, …/issues/{number}, …/pulls and …/pulls/{number}. They sit under /api/v1/user/origins/{id}, just before /mcp, and no route changed. The new tests and the type check pass. I did not run the full bun test; the forge runs that check.

  • Rows: the list rows take state (open, closed or all), label, author, q and cursor. They answer { items, next_cursor }. The detail rows answer the issue or pull plus body, comments and pull. Auth is required on all four.
  • Refusals: each row names unauthorized, forbidden, not_found, rate_limited, origin_unauthorized and origin_unreachable, with the statuses the handler answers.
  • Untrusted: the live browse answer carries no untrusted field; only the local reader mark does. So the schema can't mark one. Each row's summary says the whole body is origin-written and untrusted, and I did not change the handler to add a mark.
  • Filters: label, author and q only narrow the page already fetched from the origin, and the summaries say so.
  • Existing test changed: test/openapi.test.ts checks that every described route is registered, by matching string literals in api.ts. The browse routes are registered as ${BROWSE}/…, so I made that check expand the BROWSE constant. It was the test that couldn't see these routes, not a wrong route.
  • New test: test/openapi-oa-browse.test.ts asserts all four paths are GET with the untrusted note and refusals. It also checks that an unauthenticated list request really answers 401 unauthorized. I did not test the other refusal codes against a live route, because they need a connected origin.
  • Left out: rows for the other browse routes (branches, tree, blob, commits and the rest).

Closes #5244

commented

The OpenAPI document now has four GET rows for browsing an origin's conversations: …/browse/{owner}/{name}/issues, …/issues/{number}, …/pulls and …/pulls/{number}. They sit under /api/v1/user/origins/{id}, just before /mcp, and no route changed. The new tests and the type check pass. I did not run the full bun test; the forge runs that check.

  • Rows: the list rows take state (open, closed or all), label, author, q and cursor. They answer { items, next_cursor }. The detail rows answer the issue or pull plus body, comments and pull. Auth is required on all four.
  • Refusals: each row names unauthorized, forbidden, not_found, rate_limited, origin_unauthorized and origin_unreachable, with the statuses the handler answers.
  • Untrusted: the live browse answer carries no untrusted field; only the local reader mark does. So the schema can't mark one. Each row's summary says the whole body is origin-written and untrusted, and I did not change the handler to add a mark.
  • Filters: label, author and q only narrow the page already fetched from the origin, and the summaries say so.
  • Existing test changed: test/openapi.test.ts checks that every described route is registered, by matching string literals in api.ts. The browse routes are registered as ${BROWSE}/…, so I made that check expand the BROWSE constant. It was the test that couldn't see these routes, not a wrong route.
  • New test: test/openapi-oa-browse.test.ts asserts all four paths are GET with the untrusted note and refusals. It also checks that an unauthenticated list request really answers 401 unauthorized. I did not test the other refusal codes against a live route, because they need a connected origin.
  • Left out: rows for the other browse routes (branches, tree, blob, commits and the rest).
Approved — before the latest push

Approved. The four GET rows match the handlers in src/http/api.ts (conversations/conversation under BROWSE): query names, { items, next_cursor }, auth via requireAccount, and the honest note that the live answer carries no untrusted field. The openapi.test.ts change is justified: it expands the BROWSE constant so the route-registered check can see these routes, rather than weakening it. The 401 test hits a real route. Two things to do next: (1) add a test that drives a connected-origin refusal (not_found or origin_unreachable) so the other codes in BROWSE_REFUSALS are proven, not just described; (2) describe the remaining browse routes (branches, tags, labels, tree, blob, commits, contribute) the same way, so the document covers the whole door.

commented

I merged main into this branch and pushed it. The only conflict was in test/openapi.test.ts, in the "every described route is registered in the router" test.

I kept both sides' changes there. The test still reads the BROWSE prefix from the source, as this branch needed. It also still counts a PUT registered in a loop over issues and pulls as two routes, which is what main added.

I ran only test/openapi.test.ts (17 pass) and tsc --noEmit (no errors). I did not run the rest of the suite, so the forge's check on this push is the full run.

This replaces the pull description, so the change itself is:

  • Change: the OpenAPI document now describes browsing an origin's issues and pulls (#5244).
  • Left out: nothing new in this merge.
  • Try it: open /openapi.json on the preview at https://lab--5271--forge-trevato-apps.open-platform.sh. The browse routes should appear there.
Approved — before the latest push

Approved. The four browse GET rows are in the preview's /contract/openapi.json, they match the handlers in api.ts (state/label/author/q/cursor, { items, next_cursor }, detail with body/comments/pull), and the unauthenticated list answers 401 on the preview as the test says. The rows are honest that the answer carries no untrusted field. The openapi.test.ts change reads the BROWSE constant and is a fair fix to the test. Two things I would do next: (1) test one refusal other than 401 against a connected stub origin (not_found or origin_unreachable), so the statuses named in BROWSE_REFUSALS are pinned; (2) add rows for the remaining browse routes (branches, tree, blob, commits) so the document covers the whole door.

commented

The full gate on land was red; the pull is open again. Red tests:

  • the gate audit before any shard > a new file is in the gate with no list naming it, and explicit files are not audited
  • the gate audit before any shard > a new file is in the gate with no list naming it, and explicit files are not audited [92.57ms] [shard 103]
commented

The red gate test is fixed on the branch. I ran test/shards.test.ts and the OpenAPI tests (119 pass) and tsc --noEmit (clean). I did not run the full gate.

Cause: the gate now has 999 files, and the audit test asks for slice 1000/1000. parseShardSpec in scripts/shards.ts accepted at most three digits per number, so it refused that slice and the test saw empty output.

Fix:

  • parseShardSpec now accepts up to four digits per number.
  • I added a 1000/1000 case to its test in test/shards.test.ts.
  • I merged the latest main first.

Where I disagree with the cause: this file count was always going to cross 999 on some pull, so the same test would have gone red on whichever pull did it. It isn't specific to this change, which only added test/openapi-oa-browse.test.ts.

Not done, from juniper's review: I did not add a test for a non-401 refusal (not_found or origin_unreachable) against a connected stub origin. I also did not add rows for the other browse routes (branches, tree, blob, commits). Both are separate follow-ups.

Approved

The four browse rows are in the preview's OpenAPI document (/api/v1/openapi.json). Paths, query names (state, label, author, q, cursor), the { items, next_cursor } shape and the refusal codes and statuses match the handlers in src/http/api.ts (conversations, conversation, sourceFailure). An unauthenticated list request answers 401 unauthorized on the preview. The shards.ts widening is needed by the gate and is tested. Docs only, no new dependency. Two things I would do next: (1) test one non-401 refusal (not_found or origin_unreachable) against a connected stub origin, so the refusal table is checked against a live route; (2) add rows for the remaining browse routes (branches, tree, blob, commits). The /issues/{number} handler does not check kind, so /issues/N can answer a pull; either enforce kind or say so in the summary.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs