Implement local agent JWT authentication for adapters

Add HS256 JWT-based authentication for local adapters (claude_local, codex_local)
so agents authenticate automatically without manual API key configuration. The
server mints short-lived JWTs per heartbeat run and injects them as PAPERCLIP_API_KEY.
The auth middleware verifies JWTs alongside existing static API keys.

Includes: CLI onboard/doctor JWT secret management, env command for deployment,
config path resolution from ancestor directories, dotenv loading on server startup,
event payload secret redaction, multi-status issue filtering, and adapter transcript
parsing for thinking/user message kinds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-18 16:46:45 -06:00
parent 406f13220d
commit fe6a8687c1
28 changed files with 921 additions and 49 deletions

View File

@@ -1,8 +1,9 @@
import * as p from "@clack/prompts";
import pc from "picocolors";
import type { PaperclipConfig } from "../config/schema.js";
import { readConfig } from "../config/store.js";
import { readConfig, resolveConfigPath } from "../config/store.js";
import {
agentJwtSecretCheck,
configCheck,
databaseCheck,
llmCheck,
@@ -24,6 +25,7 @@ export async function doctor(opts: {
}): Promise<void> {
p.intro(pc.bgCyan(pc.black(" paperclip doctor ")));
const configPath = resolveConfigPath(opts.config);
const results: CheckResult[] = [];
// 1. Config check (must pass before others)
@@ -53,24 +55,30 @@ export async function doctor(opts: {
return;
}
// 2. Database check
const dbResult = await databaseCheck(config);
// 2. Agent JWT check
const jwtResult = agentJwtSecretCheck();
results.push(jwtResult);
printResult(jwtResult);
await maybeRepair(jwtResult, opts);
// 3. Database check
const dbResult = await databaseCheck(config, configPath);
results.push(dbResult);
printResult(dbResult);
await maybeRepair(dbResult, opts);
// 3. LLM check
// 4. LLM check
const llmResult = await llmCheck(config);
results.push(llmResult);
printResult(llmResult);
// 4. Log directory check
const logResult = logCheck(config);
// 5. Log directory check
const logResult = logCheck(config, configPath);
results.push(logResult);
printResult(logResult);
await maybeRepair(logResult, opts);
// 5. Port check
// 6. Port check
const portResult = await portCheck(config);
results.push(portResult);
printResult(portResult);