Tactical Media Broadcast Hub — initial release
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/.
This commit is contained in:
commit
aa5e262f3a
880 changed files with 111042 additions and 0 deletions
37
packages/core/src/shared-files.test.ts
Normal file
37
packages/core/src/shared-files.test.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
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"));
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue