T-HUB/apps/api/src/live-monitor
glass beadian aa5e262f3a 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/.
2026-10-10 11:56:42 +00:00
..
poller Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
live-monitor.controller.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
live-monitor.integration.test.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
live-monitor.module.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
live-monitor.service.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
README.md Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
reducer.test.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
reducer.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
webhook.controller.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
webhook.integration.test.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
webhook.service.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00
webhook.test.ts Tactical Media Broadcast Hub — initial release 2026-10-10 11:56:42 +00:00

Monitor signal sources

POST /live-monitor/webhooks/:endpointId authenticates providers independently of browser sessions. The module installs a raw parser before Nest's JSON parser; the request cap is 64 KiB and compressed bodies are refused.

Configure MONITOR_WEBHOOK_ENDPOINTS as a server-controlled JSON array:

[
  {
    "endpointId": "<32 server-generated random bytes, encoded as 64 lowercase hex characters>",
    "workspaceId": "<workspace UUID>",
    "connectionId": "<connection UUID>",
    "credentialId": "<credential UUID>",
    "subscriptionId": "<provider subscription id>"
  }
]

The credential must belong to that workspace and connection, have kind monitor-webhook, and contain a secret of at least 32 bytes sealed with vault.seal(workspaceId, connectionId, secret). Disconnection or credential revocation disables the endpoint. Mappings contain references, never secrets.

Send these headers:

  • X-Monitor-Event-Id: a unique provider message id (up to 256 characters).
  • X-Monitor-Timestamp: an ISO UTC timestamp within five minutes of ingestion.
  • X-Monitor-Signature: sha256= followed by lowercase hex HMAC-SHA256 over eventId + timestamp + rawBody, using the vaulted secret.

The JSON body is { "subscriptionId": "...", "sourceId": "<UUID>", "outcome": "ok|fail|error|unavailable" }. A supplied workspace or connection must also match the mapping. The source must belong to the mapped workspace and connection. Successful delivery returns 200, replay 409, authentication failure 401, unknown endpoint/source 404, invalid JSON 400, oversized body 413.

Replay ids are namespaced by endpoint in monitor_seen_events. Verification, ownership checks, replay claim, reducer fold, state write and audit share a tenant transaction. Journal pruning must retain at least the full ten-minute timestamp acceptance span plus a clock margin; this module does not prune it.

MEDIA_POLLER_SOURCES entries support playbackUrl. Provider hls probes that URL; provider peertube polls the video using the connection's fields.instanceUrl and also probes playbackUrl when supplied. Canonical video:<id>@<host> refs are supported. Existing mock configuration remains supported.

HLS probes fetch one master and one variant, validate all child URIs through WP7, and emit hls-probe observations. Decoder reports retain media-health precedence. VOD/endlist/empty/missing playlists fail; stale segments fail after three target durations. Without program dates, successive playlist progression provides recency and an initial playlist has the same bounded grace period.

Every outbound fetch uses the shared WP7 egress client and its database host bucket (monitor-probe or monitor-api), including redirect hops. Requests have a five-second total deadline, 256 KiB response cap, and 128-reference cap. Per-source drivers back off with exponential jitter after failures, honoring Retry-After seconds/dates and egress retry delays. Denied probe targets emit unavailable with a policy reason so the existing reducer can fall back.

Production requires the built packages/egress artifact and its host-budget migration/grants. Those remain owned by WP7; this module performs no DDL and implements no additional limiter.