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

The OpenAPI document describes people, organizations and agents #4857

Merged opened this

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

Merged

scout/forge:scout/4847-the-openapi-document-describes-people-or → main 5 commits fork

  • Merged. scout/4847-the-openapi-document-describes-people-or was merged into main as 5459828.

Review

Sign in to review this change.
8 files changed +47 −0
src/contract/openapi/routes/getApiV1Agents.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/agents", summary: "List the crew's agents; answers { items, next_cursor: null }; needs a signed-in caller, anonymous gets 401", auth: true };
src/contract/openapi/routes/getApiV1OrgsOrg.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/orgs/{org}", summary: "Read one organization's public profile plus `teams`, the teams the caller may see: all for an org admin, only their own for a member, [] for a stranger or anonymous caller", auth: false };
src/contract/openapi/routes/getApiV1OrgsOrgTeams.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/orgs/{org}/teams", summary: "List an organization's teams; answers { items, next_cursor }, paged by `limit` and `cursor`: all for an org admin, only the caller's own teams for a member, [] for a stranger or anonymous caller", auth: false, query: { limit: "integer", cursor: "string" } };
src/contract/openapi/routes/getApiV1OrgsOrgTeamsTeamMembers.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/orgs/{org}/teams/{team}/members", summary: "List a team's members as public profiles; answers { items, next_cursor }, paged by `limit` and `cursor`; 404 when the caller may not see the team", auth: false, query: { limit: "integer", cursor: "string" } };
src/contract/openapi/routes/getApiV1UsersUsername.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/users/{username}", summary: "Read one person's public profile; 404 when they do not exist or hid themselves from the caller", auth: false };
src/contract/openapi/routes/getApiV1UsersUsernameRepos.ts added +3
@@ -0,0 +1,3 @@
1 import type { Route } from "../shared.ts";
2
3 export const route: Route = { method: "get", path: "/api/v1/users/{username}/repos", summary: "List the repositories a person owns that the caller may see (private ones only to those with access); answers { items, next_cursor }, paged by `limit` and `cursor`", auth: false, query: { limit: "integer", cursor: "string" } };
src/contract/openapi/routes/index.ts +6
@@ -29,6 +29,7 @@ export { route as getApiV1AdminLimits } from "./getApiV1AdminLimits.ts";
2929 export { route as getApiV1AdminPeople } from "./getApiV1AdminPeople.ts";
3030 export { route as getApiV1AdminSettings } from "./getApiV1AdminSettings.ts";
3131 export { route as getApiV1AdminTeams } from "./getApiV1AdminTeams.ts";
32 export { route as getApiV1Agents } from "./getApiV1Agents.ts";
3233 export { route as getApiV1AgentsUsername } from "./getApiV1AgentsUsername.ts";
3334 export { route as getApiV1Apps } from "./getApiV1Apps.ts";
3435 export { route as getApiV1Asked } from "./getApiV1Asked.ts";
@@ -49,6 +50,9 @@ export { route as getApiV1Map } from "./getApiV1Map.ts";
4950 export { route as getApiV1MigrateJob } from "./getApiV1MigrateJob.ts";
5051 export { route as getApiV1MigrateJobStream } from "./getApiV1MigrateJobStream.ts";
5152 export { route as getApiV1OpenapiJson } from "./getApiV1OpenapiJson.ts";
53 export { route as getApiV1OrgsOrg } from "./getApiV1OrgsOrg.ts";
54 export { route as getApiV1OrgsOrgTeams } from "./getApiV1OrgsOrgTeams.ts";
55 export { route as getApiV1OrgsOrgTeamsTeamMembers } from "./getApiV1OrgsOrgTeamsTeamMembers.ts";
5256 export { route as getApiV1PassportHealth } from "./getApiV1PassportHealth.ts";
5357 export { route as getApiV1Repos } from "./getApiV1Repos.ts";
5458 export { route as getApiV1ReposOwnerName } from "./getApiV1ReposOwnerName.ts";
@@ -111,6 +115,8 @@ export { route as getApiV1UserOriginsIdBrowseOwnerNamePulls } from "./getApiV1Us
111115 export { route as getApiV1UserOriginsIdBrowseOwnerNamePullsNumber } from "./getApiV1UserOriginsIdBrowseOwnerNamePullsNumber.ts";
112116 export { route as getApiV1UserOriginsIdMirrorJob } from "./getApiV1UserOriginsIdMirrorJob.ts";
113117 export { route as getApiV1UserOriginsIdMirrorJobStream } from "./getApiV1UserOriginsIdMirrorJobStream.ts";
118 export { route as getApiV1UsersUsername } from "./getApiV1UsersUsername.ts";
119 export { route as getApiV1UsersUsernameRepos } from "./getApiV1UsersUsernameRepos.ts";
114120 export { route as getApiV1UsersUsernameSignins } from "./getApiV1UsersUsernameSignins.ts";
115121 export { route as getMetrics } from "./getMetrics.ts";
116122 export { route as patchApiV1AdminSettings } from "./patchApiV1AdminSettings.ts";
test/openapi.test.ts +23
@@ -328,3 +328,26 @@ test("the origin applications are described, and a client secret is written, nev
328328 expect(list.get.summary).toContain("hasSecret");
329329 expect(JSON.stringify(add.responses["201"])).not.toContain("clientSecret");
330330 });
331
332 test("people, organizations and agents are described", () => {
333 const doc = openapi("https://f.test", "1") as any;
334 for (const path of [
335 "/api/v1/users/{username}",
336 "/api/v1/users/{username}/repos",
337 "/api/v1/orgs/{org}",
338 "/api/v1/orgs/{org}/teams",
339 "/api/v1/orgs/{org}/teams/{team}/members",
340 "/api/v1/agents",
341 ])
342 expect(doc.paths[path]?.get, `get ${path}`).toBeDefined();
343 for (const path of [
344 "/api/v1/users/{username}/repos",
345 "/api/v1/orgs/{org}/teams",
346 "/api/v1/orgs/{org}/teams/{team}/members",
347 ]) {
348 const get = doc.paths[path].get;
349 expect(get.parameters.filter((p: any) => p.in === "query").map((p: any) => p.name), path).toEqual(["limit", "cursor"]);
350 expect(get.summary, path).toContain("next_cursor");
351 expect(get.summary, path).not.toContain("bare array");
352 }
353 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs