Add username log censor setting

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta
2026-03-20 08:00:39 -05:00
parent 3de7d63ea9
commit 39878fcdfe
33 changed files with 10841 additions and 146 deletions

View File

@@ -36,6 +36,7 @@ import { assertBoard, assertCompanyAccess, getActorInfo } from "./authz.js";
import { findServerAdapter, listAdapterModels } from "../adapters/index.js";
import { redactEventPayload } from "../redaction.js";
import { redactCurrentUserValue } from "../log-redaction.js";
import { instanceSettingsService } from "../services/instance-settings.js";
import { runClaudeLogin } from "@paperclipai/adapter-claude-local/server";
import {
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX,
@@ -64,8 +65,15 @@ export function agentRoutes(db: Db) {
const issueApprovalsSvc = issueApprovalService(db);
const secretsSvc = secretService(db);
const workspaceOperations = workspaceOperationService(db);
const instanceSettings = instanceSettingsService(db);
const strictSecretsMode = process.env.PAPERCLIP_SECRETS_STRICT_MODE === "true";
async function getCurrentUserRedactionOptions() {
return {
enabled: (await instanceSettings.getGeneral()).censorUsernameInLogs,
};
}
function canCreateAgents(agent: { role: string; permissions: Record<string, unknown> | null | undefined }) {
if (!agent.permissions || typeof agent.permissions !== "object") return false;
return Boolean((agent.permissions as Record<string, unknown>).canCreateAgents);
@@ -1597,7 +1605,7 @@ export function agentRoutes(db: Db) {
return;
}
assertCompanyAccess(req, run.companyId);
res.json(redactCurrentUserValue(run));
res.json(redactCurrentUserValue(run, await getCurrentUserRedactionOptions()));
});
router.post("/heartbeat-runs/:runId/cancel", async (req, res) => {
@@ -1632,11 +1640,12 @@ export function agentRoutes(db: Db) {
const afterSeq = Number(req.query.afterSeq ?? 0);
const limit = Number(req.query.limit ?? 200);
const events = await heartbeat.listEvents(runId, Number.isFinite(afterSeq) ? afterSeq : 0, Number.isFinite(limit) ? limit : 200);
const currentUserRedactionOptions = await getCurrentUserRedactionOptions();
const redactedEvents = events.map((event) =>
redactCurrentUserValue({
...event,
payload: redactEventPayload(event.payload),
}),
}, currentUserRedactionOptions),
);
res.json(redactedEvents);
});
@@ -1672,7 +1681,7 @@ export function agentRoutes(db: Db) {
const context = asRecord(run.contextSnapshot);
const executionWorkspaceId = asNonEmptyString(context?.executionWorkspaceId);
const operations = await workspaceOperations.listForRun(runId, executionWorkspaceId);
res.json(redactCurrentUserValue(operations));
res.json(redactCurrentUserValue(operations, await getCurrentUserRedactionOptions()));
});
router.get("/workspace-operations/:operationId/log", async (req, res) => {
@@ -1768,7 +1777,7 @@ export function agentRoutes(db: Db) {
}
res.json({
...redactCurrentUserValue(run),
...redactCurrentUserValue(run, await getCurrentUserRedactionOptions()),
agentId: agent.id,
agentName: agent.name,
adapterType: agent.adapterType,

View File

@@ -1,6 +1,6 @@
import { Router, type Request } from "express";
import type { Db } from "@paperclipai/db";
import { patchInstanceExperimentalSettingsSchema } from "@paperclipai/shared";
import { patchInstanceExperimentalSettingsSchema, patchInstanceGeneralSettingsSchema } from "@paperclipai/shared";
import { forbidden } from "../errors.js";
import { validate } from "../middleware/validate.js";
import { instanceSettingsService, logActivity } from "../services/index.js";
@@ -20,6 +20,41 @@ export function instanceSettingsRoutes(db: Db) {
const router = Router();
const svc = instanceSettingsService(db);
router.get("/instance/settings/general", async (req, res) => {
assertCanManageInstanceSettings(req);
res.json(await svc.getGeneral());
});
router.patch(
"/instance/settings/general",
validate(patchInstanceGeneralSettingsSchema),
async (req, res) => {
assertCanManageInstanceSettings(req);
const updated = await svc.updateGeneral(req.body);
const actor = getActorInfo(req);
const companyIds = await svc.listCompanyIds();
await Promise.all(
companyIds.map((companyId) =>
logActivity(db, {
companyId,
actorType: actor.actorType,
actorId: actor.actorId,
agentId: actor.agentId,
runId: actor.runId,
action: "instance.settings.general_updated",
entityType: "instance_settings",
entityId: updated.id,
details: {
general: updated.general,
changedKeys: Object.keys(req.body).sort(),
},
}),
),
);
res.json(updated.general);
},
);
router.get("/instance/settings/experimental", async (req, res) => {
assertCanManageInstanceSettings(req);
res.json(await svc.getExperimental());