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>
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import { readConfigFile } from "./config-file.js";
|
|
import { existsSync } from "node:fs";
|
|
import { config as loadDotenv } from "dotenv";
|
|
import { resolvePaperclipEnvPath } from "./paths.js";
|
|
|
|
const PAPERCLIP_ENV_FILE_PATH = resolvePaperclipEnvPath();
|
|
if (existsSync(PAPERCLIP_ENV_FILE_PATH)) {
|
|
loadDotenv({ path: PAPERCLIP_ENV_FILE_PATH, override: false, quiet: true });
|
|
}
|
|
|
|
type DatabaseMode = "embedded-postgres" | "postgres";
|
|
|
|
export interface Config {
|
|
port: number;
|
|
databaseMode: DatabaseMode;
|
|
databaseUrl: string | undefined;
|
|
embeddedPostgresDataDir: string;
|
|
embeddedPostgresPort: number;
|
|
serveUi: boolean;
|
|
uiDevMiddleware: boolean;
|
|
heartbeatSchedulerEnabled: boolean;
|
|
heartbeatSchedulerIntervalMs: number;
|
|
}
|
|
|
|
export function loadConfig(): Config {
|
|
const fileConfig = readConfigFile();
|
|
const fileDatabaseMode =
|
|
(fileConfig?.database.mode === "postgres" ? "postgres" : "embedded-postgres") as DatabaseMode;
|
|
|
|
const fileDbUrl =
|
|
fileDatabaseMode === "postgres"
|
|
? fileConfig?.database.connectionString
|
|
: undefined;
|
|
|
|
return {
|
|
port: Number(process.env.PORT) || fileConfig?.server.port || 3100,
|
|
databaseMode: fileDatabaseMode,
|
|
databaseUrl: process.env.DATABASE_URL ?? fileDbUrl,
|
|
embeddedPostgresDataDir: fileConfig?.database.embeddedPostgresDataDir ?? "./data/embedded-postgres",
|
|
embeddedPostgresPort: fileConfig?.database.embeddedPostgresPort ?? 54329,
|
|
serveUi:
|
|
process.env.SERVE_UI !== undefined
|
|
? process.env.SERVE_UI === "true"
|
|
: fileConfig?.server.serveUi ?? true,
|
|
uiDevMiddleware: process.env.PAPERCLIP_UI_DEV_MIDDLEWARE === "true",
|
|
heartbeatSchedulerEnabled: process.env.HEARTBEAT_SCHEDULER_ENABLED !== "false",
|
|
heartbeatSchedulerIntervalMs: Math.max(10000, Number(process.env.HEARTBEAT_SCHEDULER_INTERVAL_MS) || 30000),
|
|
};
|
|
}
|