PAP-10287 address teams catalog review feedback

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-05 03:45:45 +00:00
1 parent df100082e6
commit 7812174f0e
8 files changed
+242 -67

No files matched your search

+30
View File
@@ -502,6 +502,36 @@ describe("teams CLI commands", () => {
expect(errorSpy).not.toHaveBeenCalled();
});
it("does not request board approval for unrelated forbidden install errors", async () => {
fetchMock.mockResolvedValueOnce(jsonResponse({ error: "Agent key cannot access another company" }, 403));
vi.spyOn(process, "exit").mockImplementation(((code?: string | number | null) => {
throw new Error(`exit:${code ?? 0}`);
}) as typeof process.exit);
await expect(runCommand([
"teams",
"install",
"product-engineering",
"--company-id",
"company-1",
"--request-approval-on-forbidden",
"--api-base",
"http://paperclip.test",
"--api-key",
"token",
])).rejects.toThrow("exit:1");
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith(
"http://paperclip.test/api/companies/company-1/teams/catalog/ref/install?ref=product-engineering",
expect.objectContaining({
method: "POST",
body: JSON.stringify({}),
}),
);
expect(String(errorSpy.mock.calls[0]?.[0])).toContain("Agent key cannot access another company");
});
it("surfaces server blocks for unsafe local-path catalog team sources", async () => {
fetchMock.mockResolvedValueOnce(jsonResponse({
error: 'Local path skill source "../unsafe" is development-only and is not allowed for catalog team install.',
+2 -2
View File
@@ -1750,11 +1750,11 @@ async function resolveCurrentCompanyId(ctx: { companyId?: string; api: { get<T>(
}
function isBoardAccessRequiredError(error: unknown): error is ApiRequestError {
return error instanceof ApiRequestError && error.status === 403 && error.message.includes("Board access required");
return error instanceof ApiRequestError && error.status === 403 && error.message.toLowerCase().includes("board access required");
}
function isInstanceAdminRequiredError(error: unknown): error is ApiRequestError {
return error instanceof ApiRequestError && error.status === 403 && error.message.includes("Instance admin");
return error instanceof ApiRequestError && error.status === 403 && error.message.toLowerCase().includes("instance admin");
}
function addCompanyJsonPost(parent: Command, name: string, description: string, pathSuffix: string): void {
+9 -5
View File
@@ -361,12 +361,16 @@ function buildTeamInstallOptions(opts: TeamInstallOptions): CatalogTeamInstallOp
return buildTeamOptions(opts);
}
const INSTALL_APPROVAL_FALLBACK_MESSAGES = [
"missing permission: agents:create",
"missing permission: can create agents",
];
function shouldRequestInstallApproval(error: unknown, opts: TeamInstallOptions): error is ApiRequestError {
return Boolean(
(opts.requestApprovalOnForbidden || isPaperclipTaskRun()) &&
error instanceof ApiRequestError &&
error.status === 403,
);
if (!(opts.requestApprovalOnForbidden || isPaperclipTaskRun())) return false;
if (!(error instanceof ApiRequestError) || error.status !== 403) return false;
const message = error.message.toLowerCase();
return INSTALL_APPROVAL_FALLBACK_MESSAGES.some((expected) => message.includes(expected));
}
function isPaperclipTaskRun(): boolean {