mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-10 12:37:55 +01:00
fix(api): tell agents how a person connects their terminal
The CLI auth operations in the agent API catalog had bare summaries, so a
chat agent asked to connect a person's terminal could find the endpoints but
not who starts the flow, and spent its whole turn reading source code to find
the command. Describe the person-run paperclipai auth login flow, the browser
approval, whoami/logout, and that agents must not create or approve challenges,
hand out agent keys or ask for passwords.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit a042ee497d)
This commit is contained in:
1 parent
6db5670232
commit
61f08992c8
2 files changed
+31
-1
No files matched your search
@@ -0,0 +1,26 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { searchRunnerApi } from "../services/native-runtime/runner-api-catalog.js";
|
||||
|
||||
// A chat agent asked to "connect my terminal to Paperclip as me" searched the
|
||||
// API catalog, found the CLI auth operations without any statement of who starts
|
||||
// the flow, and spent its whole turn reading source code to find the command.
|
||||
describe("CLI terminal login guidance in the agent API catalog", () => {
|
||||
it.each([
|
||||
"connect my terminal to Paperclip as me",
|
||||
"terminal connect CLI login pair device link personal access",
|
||||
"cli-auth login code approve session token terminal",
|
||||
])("search %j finds the person-run CLI login command", query => {
|
||||
const { results } = searchRunnerApi({ query, limit: 5 });
|
||||
const challenge = results.find(operation => operation.operationId === "POST /api/cli-auth/challenges");
|
||||
expect(challenge, query).toBeDefined();
|
||||
expect(challenge!.description).toContain("`npx paperclipai auth login --api-base <this Paperclip URL>`");
|
||||
expect(challenge!.description).toContain("never by an agent on their behalf");
|
||||
expect(challenge!.description).toMatch(/never hand out an agent key, create or approve a challenge yourself, or ask for the person's password/);
|
||||
});
|
||||
|
||||
it("tells agents that only the signed-in person can approve", () => {
|
||||
const { results } = searchRunnerApi({ query: "POST /api/cli-auth/challenges/{id}/approve" });
|
||||
expect(results[0]?.description).toContain("agent API keys receive 401");
|
||||
expect(results[0]?.description).toContain("`npx paperclipai auth login`");
|
||||
});
|
||||
});
|
||||
@@ -7401,6 +7401,7 @@ registry.registerPath({
|
||||
path: "/api/cli-auth/me",
|
||||
tags: ["access"],
|
||||
summary: "Get current CLI auth session",
|
||||
description: "Board-credential read used by `npx paperclipai auth whoami` in the person's own terminal. Agent API keys receive 401: an agent cannot sign a terminal in as a person. To connect someone's terminal, see POST /api/cli-auth/challenges.",
|
||||
responses: { 200: r.ok(), 401: r.unauthorized },
|
||||
});
|
||||
|
||||
@@ -7420,7 +7421,8 @@ registry.registerPath({
|
||||
method: "post",
|
||||
path: "/api/cli-auth/challenges",
|
||||
tags: ["access"],
|
||||
summary: "Create a CLI auth challenge",
|
||||
summary: "Connect a person's terminal to Paperclip: create a CLI auth challenge for terminal login",
|
||||
description: "Called by the Paperclip CLI in a person's own terminal, never by an agent on their behalf. To connect someone's terminal to Paperclip as themselves, tell them to run `npx paperclipai auth login --api-base <this Paperclip URL>` in that terminal (add `--company-id <companyId>` to name the company). The CLI prints an approval link; they open it in a browser where they are signed in, review the requesting command, company and Board access, and approve. Only that CLI receives the resulting Board credential. `npx paperclipai auth whoami` confirms who it is signed in as and `npx paperclipai auth logout` revokes it. Agent API keys are a separate identity: never hand out an agent key, create or approve a challenge yourself, or ask for the person's password in chat.",
|
||||
request: { body: jsonBody(createCliAuthChallengeSchema) },
|
||||
responses: { 200: r.ok(), 400: r.badRequest },
|
||||
});
|
||||
@@ -7430,6 +7432,7 @@ registry.registerPath({
|
||||
path: "/api/cli-auth/challenges/{id}/approve",
|
||||
tags: ["access"],
|
||||
summary: "Approve a CLI auth challenge",
|
||||
description: "Only the signed-in person approves, from the approval page their own CLI printed; agent API keys receive 401. To connect someone's terminal, give them the `npx paperclipai auth login` command (see POST /api/cli-auth/challenges).",
|
||||
request: {
|
||||
params: z.object({ id: cliAuthChallengeIdParamSchema }),
|
||||
body: jsonBody(resolveCliAuthChallengeSchema),
|
||||
@@ -7459,6 +7462,7 @@ registry.registerPath({
|
||||
path: "/api/cli-auth/revoke-current",
|
||||
tags: ["access"],
|
||||
summary: "Revoke current CLI auth session",
|
||||
description: "Used by `npx paperclipai auth logout` with the CLI's own Board credential; it revokes only that credential and leaves agent API keys untouched.",
|
||||
responses: { 200: r.ok(), 401: r.unauthorized },
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user