content-distribution-source — TYPO3 pushes TYPO3, signed and replay-safe.

One central editorial TYPO3 (the “source”) pushes content to n downstream TYPO3 instances (the “targets”). Editors keep working in the familiar backend; the distribution triggers on workspace-to-live publish, signs the payload with Ed25519 and delivers a DAG-structured snapshot — referenced via UUIDv7, never via TYPO3 UID. The companion moselwal/content-distribution-receiver receives the snapshot and writes it into the local schema.

Why a separate package

moselwal/semantic-delivery distributes content to external channels — LinkedIn, Buffer, n8n, generic webhooks. It knows nothing about:

content-distribution-source fills exactly this gap. It reuses the SSRF-safe URL validator, the Ed25519 key infrastructure from moselwal/content-provenance and the rate-limit / nonce patterns from moselwal/webmcp.

Requirements

Transport, authentication and scope

Transport — hybrid push and pull

  1. Push ping: on workspace-to-live publish the source sends a small signed webhook to each subscribed target announcing what changed.
  2. Pull fetch: the target authenticates back to the source’s pull endpoint and downloads the full DAG snapshot.
  3. Ack: the target acknowledges; the source marks the outbox entry as acked.

Snapshots reference all records by origin_uuid (UUIDv7) — never by TYPO3 UID. This lets the receiver resolve foreign keys against its own ID space without UIDs colliding between instances.

Workspace integration

Distribution is only triggered when a record is staged to live in a TYPO3 workspace. Drafts never leak. The trigger is a TYPO3-14 event listener with a DataHandler hook as a fallback.

Authentication

Scope — what is distributed out of the box

Installation, quick start and commands

Installation

 

composer require moselwal/content-distribution-source
vendor/bin/typo3 extension:setup

 

Schema migrations add origin_uuid columns to pages, tt_content, sys_file* and the package tables tx_cdsource_target and tx_cdsource_outbox.

Quick start

 

# Register a target instance
vendor/bin/typo3 cdsource:targets:add \
  --label="Production EN" \
  --base-url="https://en.example.com" \
  --subscribed-tables="pages,tt_content,sys_file_reference" \
  --subscribed-languages="0,1"

# Process the outbox (from cron or scheduler)
vendor/bin/typo3 cdsource:outbox:process

 

CLI commands

CommandPurpose
cdsource:targets:listList configured targets
cdsource:targets:addRegister a target instance
cdsource:targets:testSend a probe ping to a target
cdsource:outbox:processSend all pending and retryable entries
cdsource:outbox:retryRe-enqueue failed entries
cdsource:outbox:purgeClean up old acked entries

Backend modules

Architecture (DDD 4-Layer)

Strict DDD 4-layer architecture, enforced via deptrac:

LayerMay depend on
DomainMoselwal\ContentProvenance\* (interface only)
ApplicationDomain, ContentProvenance
InfrastructureApplication, Domain, Framework, ContentProvenance, StructuredContent
PresentationApplication, Domain, Framework

License GPL-2.0-or-later (see repo). Codebase guidance: CLAUDE.md inside the package.

Part of the content distribution line

Next step

Setting up TYPO3-to-TYPO3 distribution?

If you maintain editorial content centrally and want to push it to several TYPO3 brand sites without going headless and without breaking the editor workflow, content-distribution-source is the right layer. Get in touch for architecture advice, multi-site setup and migration from existing syndication solutions.

Discuss distribution

Or email us directly: kontakt@moselwal.de

Where we use this …

This package carries the multi-site and multi-region syndication in TYPO3 Kubernetes and is part of sovereign platforms as described under Open Source & Digital Sovereignty. Managed variant: AI-Ready CMS as a Service.