import { randomUUID } from "node:crypto"; import { describe, expect, it } from "vitest"; import { ConnectorRegistry } from "@tactical-media-broadcast-hub/connector-sdk"; import type { ConnectorConnection, FeedItem } from "@tactical-media-broadcast-hub/core"; import { createMockSocialConnector, createMockSocialState } from "../../../../packages/connector-mock-social/src/index.js"; import { DEFAULT_MEDIA_PROXY, parseProviderHtml, type CustomEmoji, type LinkPreview, type MediaProxyPolicy, type RichTextDocument } from "../../../../packages/safe-content/src/index.js"; import { astToPlainText, feedAuthorRef, feedItemMedia, normalizeFeedItem, type MediaRef, type NormalizedFeedItem } from "./feed-normalize.js"; import { FeedsService, feedCacheKey } from "./feeds.service.js"; import type { FeedDependencies } from "./feeds.dependencies.js"; import { MemoryFeedRedis } from "./testing.js"; /** Per-connector fixtures (design §3.2 provider table) + hostile-HTML cases. */ interface ProviderFixture { provider: string; contentKind?: "text" | "html"; instanceUrl?: string; emojis?: readonly CustomEmoji[]; item: FeedItem; url?: unknown; expiresAt?: unknown; linkPreview?: unknown; } const PROXY: MediaProxyPolicy = DEFAULT_MEDIA_PROXY; const connection = (fields: Record = {}): ConnectorConnection => ({ id: "conn-1", workspaceId: "ws-1", provider: "mastodon", channelId: "conn-1", credentialId: { kind: "credential-ref", id: "cred-1" }, fields, createdAt: new Date(), }); const mastodonStatus: FeedItem = { id: "1001", provider: "mastodon", remoteId: "1001", authorHandle: "alice@foreso.social", // The exact HTML shape Mastodon emits: p/br/a, mention + hashtag + invisible // ellipsis link spans, HTML-escaped ampersands, raw emoji tags. text: '

A call for @bob & friends

# kicks off example.org/manifes :ok:
line two bolded

', mediaUrls: ["https://cdn.foreso.social/media/1234.png", "https://cdn.foreso.social/media/clip.mp4"], createdAt: new Date("2026-10-06T12:00:00.000Z"), metrics: { reblogs: 2, replies: 1, favourites: 5, broken: Number.NaN, infinite: Number.POSITIVE_INFINITY }, }; const xssStatus: FeedItem = { id: "2002", provider: "mastodon", remoteId: "2002", authorHandle: "mallory@evil.example", text: '

hi clickpasstabbed

after

', mediaUrls: ["javascript:alert(5)", "data:text/html,evil", "//protocol-relative.example/x.png", "https://cdn.example/ok.png"], createdAt: new Date("2026-10-06T12:01:00.000Z"), metrics: {}, }; const fixturePlainText: ProviderFixture = { // Plain-text provider source (Bluesky/Telegram-style): auto-linked, no HTML. provider: "bluesky", item: { id: "1", provider: "bluesky", remoteId: "at://did:plc:abc/app.bsky.feed.post/1", authorHandle: "acampada.bsky.social", mediaUrls: [], createdAt: new Date("2026-10-06T10:00:00.000Z"), metrics: { likes: 3 }, text: "Line one\n\n hub https://github.com/eche/acampada26/blob/main/core/search.ts #acampada26 @alice@foreso.social", }, url: "https://bsky.app/profile/acampada.bsky.social/post/1", }; const fixtureMastodonHtml: ProviderFixture = { // Mastodon status HTML: allowlist parser, mention + ellipsis link + emoji. provider: "mastodon", contentKind: "html", emojis: [{ shortcode: "ok", url: "https://foreso.social/emoji/ok.png" }], item: mastodonStatus, url: "https://foreso.social/@alice/1001", }; const fixtureHostileHtml: ProviderFixture = { // Hostile HTML from a compromised/bogus federated peer. provider: "mastodon", contentKind: "html", instanceUrl: "https://EVIL.example:443/", item: xssStatus, url: "javascript:alert(6)", linkPreview: { url: "javascript:alert(7)", title: "javascript:alert(8)", image: "javascript:alert(9)" }, }; const fixtureMastodonLinkPreview: ProviderFixture = { // Mastodon HTML + card (link-preview) payload as one source row. provider: "mastodon", contentKind: "html", item: { ...mastodonStatus, id: "1002", remoteId: "1002", text: '

with a @bob card

', mediaUrls: [] }, url: "https://foreso.social/@alice/1002", linkPreview: { url: "https://example.org/manifesto", title: "Manifesto <scripts> & plans", description: "A plan", siteName: "example dot org", image: "https://cdn.example.org/cover.png", }, }; const fixtures: Record<"plainText" | "mastodonHtml" | "hostileHtml" | "mastodonLinkPreview", ProviderFixture> = { plainText: fixturePlainText, mastodonHtml: fixtureMastodonHtml, hostileHtml: fixtureHostileHtml, mastodonLinkPreview: fixtureMastodonLinkPreview, }; /** No provider CDN URL outside the media-proxy query string, ever. */ function assertProxyOnly(media: MediaRef[]): void { const serialized = JSON.stringify(media); let index = serialized.indexOf("https://"); while (index !== -1) { expect(serialized.slice(0, index)).toContain(`${PROXY.proxyPath}?url=`); index = serialized.indexOf("https://", index + 1); } for (const ref of media) expect(ref.proxyUrl.startsWith(`${PROXY.proxyPath}?url=`)).toBe(true); } /** Raw-remnant scan applied to every fixture's AST, plain text and media. */ function assertZeroRawRemnants(ast: RichTextDocument, plainText: string, media: MediaRef[]): void { const astJson = JSON.stringify(ast); const hostile: RegExp[] = [ /<\s*(script|iframe|style|img|svg|math|template|form|object|embed|applet|frame)\b/i, /<\s*\/\s*/, /