feat(cli): add deployment mode prompts, auth bootstrap-ceo command, and doctor check
Extend server setup prompts with deployment mode (local_trusted vs authenticated), exposure (private vs public), bind host, and auth config. Add auth bootstrap-ceo command that creates a one-time invite URL for the initial instance admin. Add deployment-auth-check to doctor diagnostics. Register the new command in the CLI entry point. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
91
cli/src/checks/deployment-auth-check.ts
Normal file
91
cli/src/checks/deployment-auth-check.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { PaperclipConfig } from "../config/schema.js";
|
||||
import type { CheckResult } from "./index.js";
|
||||
|
||||
function isLoopbackHost(host: string) {
|
||||
const normalized = host.trim().toLowerCase();
|
||||
return normalized === "127.0.0.1" || normalized === "localhost" || normalized === "::1";
|
||||
}
|
||||
|
||||
export function deploymentAuthCheck(config: PaperclipConfig): CheckResult {
|
||||
const mode = config.server.deploymentMode;
|
||||
const exposure = config.server.exposure;
|
||||
const auth = config.auth;
|
||||
|
||||
if (mode === "local_trusted") {
|
||||
if (!isLoopbackHost(config.server.host)) {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "fail",
|
||||
message: `local_trusted requires loopback host binding (found ${config.server.host})`,
|
||||
canRepair: false,
|
||||
repairHint: "Run `paperclip configure --section server` and set host to 127.0.0.1",
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "pass",
|
||||
message: "local_trusted mode is configured for loopback-only access",
|
||||
};
|
||||
}
|
||||
|
||||
const secret =
|
||||
process.env.BETTER_AUTH_SECRET?.trim() ??
|
||||
process.env.PAPERCLIP_AGENT_JWT_SECRET?.trim();
|
||||
if (!secret) {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "fail",
|
||||
message: "authenticated mode requires BETTER_AUTH_SECRET (or PAPERCLIP_AGENT_JWT_SECRET)",
|
||||
canRepair: false,
|
||||
repairHint: "Set BETTER_AUTH_SECRET before starting Paperclip",
|
||||
};
|
||||
}
|
||||
|
||||
if (auth.baseUrlMode === "explicit" && !auth.publicBaseUrl) {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "fail",
|
||||
message: "auth.baseUrlMode=explicit requires auth.publicBaseUrl",
|
||||
canRepair: false,
|
||||
repairHint: "Run `paperclip configure --section server` and provide a base URL",
|
||||
};
|
||||
}
|
||||
|
||||
if (exposure === "public") {
|
||||
if (auth.baseUrlMode !== "explicit" || !auth.publicBaseUrl) {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "fail",
|
||||
message: "authenticated/public requires explicit auth.publicBaseUrl",
|
||||
canRepair: false,
|
||||
repairHint: "Run `paperclip configure --section server` and select public exposure",
|
||||
};
|
||||
}
|
||||
try {
|
||||
const url = new URL(auth.publicBaseUrl);
|
||||
if (url.protocol !== "https:") {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "warn",
|
||||
message: "Public exposure should use an https:// auth.publicBaseUrl",
|
||||
canRepair: false,
|
||||
repairHint: "Use HTTPS in production for secure session cookies",
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "fail",
|
||||
message: "auth.publicBaseUrl is not a valid URL",
|
||||
canRepair: false,
|
||||
repairHint: "Run `paperclip configure --section server` and provide a valid URL",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: "Deployment/auth mode",
|
||||
status: "pass",
|
||||
message: `Mode ${mode}/${exposure} with auth URL mode ${auth.baseUrlMode}`,
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,7 @@ export interface CheckResult {
|
||||
|
||||
export { agentJwtSecretCheck } from "./agent-jwt-secret-check.js";
|
||||
export { configCheck } from "./config-check.js";
|
||||
export { deploymentAuthCheck } from "./deployment-auth-check.js";
|
||||
export { databaseCheck } from "./database-check.js";
|
||||
export { llmCheck } from "./llm-check.js";
|
||||
export { logCheck } from "./log-check.js";
|
||||
|
||||
Reference in New Issue
Block a user