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
48
packages/connector-runtime/src/policy.ts
Normal file
48
packages/connector-runtime/src/policy.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import type { ConnectorConnection } from "@tactical-media-broadcast-hub/core";
|
||||
/**
|
||||
* Provider publishing policies, declared at the composition boundary so the
|
||||
* SDK publish/deletePublication signatures stay unchanged.
|
||||
*/
|
||||
export interface PublishingPolicy {
|
||||
/**
|
||||
* "token": the provider dedupes repeated sends carrying the same
|
||||
* idempotency key, so an ambiguous send may be replayed with that key.
|
||||
* "none": no key and no lookup — an ambiguous send is never replayed.
|
||||
*/
|
||||
idempotency: "token" | "none";
|
||||
/**
|
||||
* How long after the attempt's first dispatch a same-key replay is trusted.
|
||||
* Applies only to "token" policies and only on deployment-verified origins.
|
||||
*/
|
||||
dedupeWindowMs?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mastodon documents Idempotency-Key retention of up to one hour; 30 minutes
|
||||
* from first dispatch is the deployment cutoff (forks may keep less).
|
||||
*/
|
||||
export const MASTODON_DEDUPE_WINDOW_MS = 30 * 60 * 1000;
|
||||
|
||||
export const PUBLISHING_POLICIES: Readonly<Record<string, PublishingPolicy>> = {
|
||||
mastodon: { idempotency: "token", dedupeWindowMs: MASTODON_DEDUPE_WINDOW_MS },
|
||||
telegram: { idempotency: "none" },
|
||||
};
|
||||
|
||||
/** Unknown providers get the safe default: never replay an ambiguous send. */
|
||||
export function publishingPolicyFor(provider: string): PublishingPolicy {
|
||||
return PUBLISHING_POLICIES[provider] ?? { idempotency: "none" };
|
||||
}
|
||||
|
||||
export function verifiedDedupeOrigin(origin: string, configured = process.env.MASTODON_PUBLISH_DEDUPE_ORIGINS ?? ""): boolean {
|
||||
return configured.split(",").map((value) => value.trim()).filter(Boolean).some((value) => {
|
||||
try { const url = new URL(value); return url.protocol === "https:" && url.origin === value && url.origin === origin; } catch { return false; }
|
||||
});
|
||||
}
|
||||
|
||||
export function isPublishingProvider(provider: string): boolean { return Object.hasOwn(PUBLISHING_POLICIES, provider); }
|
||||
export function publishingDispatchPolicy(connection: ConnectorConnection): { policy: PublishingPolicy; origin: string; dedupeVerified: boolean } {
|
||||
const policy = publishingPolicyFor(connection.provider);
|
||||
let origin = "";
|
||||
try { origin = new URL(connection.fields.instanceUrl ?? "").origin; } catch { /* invalid origins never authorize dedupe */ }
|
||||
return { policy, origin, dedupeVerified: policy.idempotency === "token" && verifiedDedupeOrigin(origin) };
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue