Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
37 lines
2 KiB
TypeScript
37 lines
2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { attachmentArchiveKey, canArchiveAttachment, type GroupFileMapping, type MatrixAttachmentCandidate } from "./shared-files.js";
|
|
|
|
const mapping: GroupFileMapping = {
|
|
workspaceId: "workspace", groupId: "group", roomId: "!archive:example.org",
|
|
spaceId: "space", folderId: "folder", archivePolicy: "unencrypted-archive",
|
|
retention: { mode: "keep", legalHold: false },
|
|
};
|
|
const event: MatrixAttachmentCandidate = {
|
|
roomId: mapping.roomId, eventId: "$event", senderId: "@sender:example.org",
|
|
eventType: "m.room.message", msgtype: "m.file", roomEncryption: "unencrypted",
|
|
encryptedFile: false, redacted: false, mxcUri: "mxc://example.org/media",
|
|
};
|
|
|
|
describe("group file archive policy", () => {
|
|
it("accepts only attachments in an explicitly mapped unencrypted archive room", () => {
|
|
for (const msgtype of ["m.file", "m.image", "m.audio", "m.video"]) {
|
|
expect(canArchiveAttachment(mapping, { ...event, msgtype })).toBe(true);
|
|
}
|
|
expect(canArchiveAttachment({ ...mapping, archivePolicy: "disabled" }, event)).toBe(false);
|
|
expect(canArchiveAttachment(mapping, { ...event, roomId: "!other:example.org" })).toBe(false);
|
|
});
|
|
|
|
it("fails closed on encryption, unknown state, redactions and non-attachment messages", () => {
|
|
for (const patch of [
|
|
{ roomEncryption: "encrypted" as const }, { roomEncryption: "unknown" as const },
|
|
{ encryptedFile: true }, { redacted: true }, { eventType: "m.room.encrypted" },
|
|
{ msgtype: "m.text" }, { mxcUri: "https://attacker.example/file" }, { mxcUri: "mxc://example.org/" },
|
|
]) expect(canArchiveAttachment(mapping, { ...event, ...patch })).toBe(false);
|
|
});
|
|
|
|
it("replays use the same identity without conflating tenants or rooms", () => {
|
|
expect(attachmentArchiveKey("w", "r", "e")).toBe(attachmentArchiveKey("w", "r", "e"));
|
|
expect(attachmentArchiveKey("w2", "r", "e")).not.toBe(attachmentArchiveKey("w", "r", "e"));
|
|
expect(attachmentArchiveKey("a:b", "c", "e")).not.toBe(attachmentArchiveKey("a", "b:c", "e"));
|
|
});
|
|
});
|