Harden Clip publish moderation defaults

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-09 19:47:39 +00:00
1 parent e10d403e5e
commit 24b1191ca2
2 files changed
+63 -1

No files matched your search

+53
View File
@@ -168,6 +168,59 @@ describe("clip routes", () => {
vi.clearAllMocks();
});
it("normalizes public publish moderation and trust states before persistence", async () => {
const companyId = "11111111-1111-4111-8111-111111111111";
const clipId = "22222222-2222-4222-8222-222222222222";
const revisionId = "33333333-3333-4333-8333-333333333333";
mockClipService.publish.mockResolvedValue({
clip: {
id: clipId,
slug: "support-triage",
visibility: "public",
status: "pending_review",
},
revision: {
id: revisionId,
revisionNumber: 1,
},
creatorProfile: {
id: "44444444-4444-4444-8444-444444444444",
},
});
const res = await request(createApp())
.post(`/api/companies/${companyId}/clips/publish`)
.send({
creatorProfile: {
handle: "support-team",
displayName: "Support Team",
},
slug: "support-triage",
type: "bundle",
title: "Support Triage",
summary: "Routes support tickets.",
visibility: "public",
status: "published",
revision: {
manifestChecksum: HASH,
artifactChecksum: HASH,
manifestPayload: { ok: true },
securityReviewState: "security_reviewed",
verificationState: "passed",
},
});
expect(res.status).toBe(201);
expect(mockClipService.publish).toHaveBeenCalledWith(companyId, expect.objectContaining({
visibility: "public",
status: "pending_review",
revision: expect.objectContaining({
securityReviewState: "unreviewed",
verificationState: "not_run",
}),
}));
});
it("rejects malformed companyId path params before share-preview database lookups", async () => {
const res = await request(createApp())
.post("/api/companies/random-company-id/clips/share-preview")
+10 -1
View File
@@ -510,7 +510,16 @@ export function clipRoutes(db: Db, storage?: StorageService) {
const companyId = getClipCompanyIdParam(req);
assertCompanyAccess(req, companyId);
if (!consumeClipRateLimit(req, res, "publish")) return;
const result = await svc.publish(companyId, req.body);
const publishInput = {
...req.body,
status: req.body.visibility === "public" ? "pending_review" as const : req.body.status,
revision: {
...req.body.revision,
securityReviewState: "unreviewed" as const,
verificationState: "not_run" as const,
},
};
const result = await svc.publish(companyId, publishInput);
const actor = getActorInfo(req);
await logActivity(db, {
companyId,