diff --git a/server/src/__tests__/openapi-routes.test.ts b/server/src/__tests__/openapi-routes.test.ts index 212e26eb5a2..e0ebdac2cad 100644 --- a/server/src/__tests__/openapi-routes.test.ts +++ b/server/src/__tests__/openapi-routes.test.ts @@ -238,6 +238,19 @@ function loadSpecRoutes() { } describe("openapi routes", () => { + it("documents manager-only task privacy hints without protected scope identity", () => { + const spec = buildOpenApiSpec() as any; + const operation = spec.paths["/api/issues/{id}/privacy-constraints"].get; + const schema = operation.responses["200"].content["application/json"].schema; + expect(schema.properties).toEqual({ + publicBlockedBy: { type: "string", enum: ["parent", "project"], nullable: true }, + leavesPersonalProject: { type: "boolean" }, + }); + expect(schema.required).toEqual(["publicBlockedBy", "leavesPersonalProject"]); + expect(operation.responses["403"]).toBeDefined(); + expect(operation.responses["404"]).toBeDefined(); + }); + it("documents strict run-attributed feedback without a read endpoint", () => { const { spec } = loadSpecRoutes(); const path = spec.paths["/api/companies/{companyId}/agent-commentary"]; diff --git a/server/src/routes/openapi.ts b/server/src/routes/openapi.ts index 2ccf5f8cd97..b82b467bde6 100644 --- a/server/src/routes/openapi.ts +++ b/server/src/routes/openapi.ts @@ -4325,6 +4325,24 @@ registry.registerPath({ responses: { 200: r.ok(), 401: r.unauthorized }, }); +registry.registerPath({ + method: "get", + path: "/api/issues/{id}/privacy-constraints", + tags: ["issues"], + summary: "Get task privacy action constraints for an authorized manager", + description: "Returns action hints without disclosing protected parent or project identity. Visibility writes recheck the current rules under the privacy-tree lock.", + request: { params: z.object({ id: z.string() }) }, + responses: { + 200: r.ok(z.object({ + publicBlockedBy: z.enum(["parent", "project"]).nullable(), + leavesPersonalProject: z.boolean(), + }).strict()), + 401: r.unauthorized, + 403: r.forbidden, + 404: r.notFound, + }, +}); + registry.registerPath({ method: "get", path: "/api/issues/{id}/access-grants",