mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
fix: harden activity detail truncation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
8ca764a45e
commit
35e3d84be0
5 files changed
+16
-3
No files matched your search
@@ -38,6 +38,7 @@ describe("capActivityDetails", () => {
|
||||
});
|
||||
expect(capped?._paperclipOriginalBytes).toBeGreaterThan(MAX_ACTIVITY_DETAILS_BYTES);
|
||||
expect(capped?._paperclipPreview).toEqual(expect.stringContaining("start-"));
|
||||
expect(/[\uD800-\uDBFF]$/.test(String(capped?._paperclipPreview))).toBe(false);
|
||||
expect(Buffer.byteLength(JSON.stringify(capped), "utf8")).toBeLessThanOrEqual(
|
||||
MAX_ACTIVITY_DETAILS_BYTES,
|
||||
);
|
||||
@@ -161,7 +162,7 @@ describeEmbeddedPostgres("activity log retention", () => {
|
||||
action: "test.oversized",
|
||||
entityType: "company",
|
||||
entityId: companyId,
|
||||
details: { output: "x".repeat(MAX_ACTIVITY_DETAILS_BYTES * 2) },
|
||||
details: { output: "😀".repeat(MAX_ACTIVITY_DETAILS_BYTES) },
|
||||
});
|
||||
|
||||
const row = await db
|
||||
|
||||
+1
-1
@@ -827,7 +827,7 @@ export async function startServer(): Promise<StartedServer> {
|
||||
let prepareHotRestartShutdown: ((signal: "SIGINT" | "SIGTERM") => Promise<{ skipDrain: boolean }>) | null = null;
|
||||
let heartbeatSchedulerStopped = false;
|
||||
let heartbeatSchedulerInterval: ReturnType<typeof setInterval> | null = null;
|
||||
const stopActivityLogRetention = startActivityLogRetention(db as any);
|
||||
const stopActivityLogRetention = startActivityLogRetention(db);
|
||||
const heartbeatSchedulerInFlight = new Set<Promise<void>>();
|
||||
const trackHeartbeatSchedulerWork = (work: Promise<unknown>) => {
|
||||
let tracked: Promise<void>;
|
||||
|
||||
@@ -99,7 +99,15 @@ export function capActivityDetails(
|
||||
}
|
||||
}
|
||||
|
||||
return buildMarker(serialized.slice(0, low));
|
||||
const finalCodeUnit = serialized.charCodeAt(low - 1);
|
||||
const nextCodeUnit = serialized.charCodeAt(low);
|
||||
const splitsSurrogatePair = finalCodeUnit >= 0xd800
|
||||
&& finalCodeUnit <= 0xdbff
|
||||
&& nextCodeUnit >= 0xdc00
|
||||
&& nextCodeUnit <= 0xdfff;
|
||||
const previewEnd = splitsSurrogatePair ? low - 1 : low;
|
||||
|
||||
return buildMarker(serialized.slice(0, previewEnd));
|
||||
}
|
||||
|
||||
export async function resolveResponsibleUserIdForActivity(db: Db, input: LogActivityInput) {
|
||||
|
||||
@@ -39,6 +39,7 @@ function makeCompany(id: string): Company {
|
||||
budgetMonthlyCents: 0,
|
||||
spentMonthlyCents: 0,
|
||||
attachmentMaxBytes: 10 * 1024 * 1024,
|
||||
activityLogRetentionDays: null,
|
||||
defaultResponsibleUserId: null,
|
||||
requireBoardApprovalForNewAgents: false,
|
||||
feedbackDataSharingEnabled: false,
|
||||
|
||||
@@ -43,6 +43,7 @@ export const storybookCompanies: Company[] = [
|
||||
budgetMonthlyCents: 250_000,
|
||||
spentMonthlyCents: 67_500,
|
||||
attachmentMaxBytes: 10 * 1024 * 1024,
|
||||
activityLogRetentionDays: null,
|
||||
defaultResponsibleUserId: "user-board",
|
||||
requireBoardApprovalForNewAgents: true,
|
||||
feedbackDataSharingEnabled: true,
|
||||
@@ -67,6 +68,7 @@ export const storybookCompanies: Company[] = [
|
||||
budgetMonthlyCents: 180_000,
|
||||
spentMonthlyCents: 39_500,
|
||||
attachmentMaxBytes: 10 * 1024 * 1024,
|
||||
activityLogRetentionDays: null,
|
||||
defaultResponsibleUserId: "user-board",
|
||||
requireBoardApprovalForNewAgents: false,
|
||||
feedbackDataSharingEnabled: false,
|
||||
@@ -91,6 +93,7 @@ export const storybookCompanies: Company[] = [
|
||||
budgetMonthlyCents: 90_000,
|
||||
spentMonthlyCents: 91_200,
|
||||
attachmentMaxBytes: 10 * 1024 * 1024,
|
||||
activityLogRetentionDays: null,
|
||||
defaultResponsibleUserId: "user-board",
|
||||
requireBoardApprovalForNewAgents: true,
|
||||
feedbackDataSharingEnabled: false,
|
||||
|
||||
Reference in new issue
Block a user