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:
- multiple TYPO3 instances as peers
- workspace publish triggers
- TYPO3-native record snapshots (pages plus tt_content plus FAL)
- per-language local edits on the receiver side
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
- TYPO3 14.x
- Composer package
moselwal/content-distribution-source - Optional:
moselwal/content-provenancefor Vault-backed key providers,moselwal/structured-contentfor relations and annotations
Transport, authentication and scope
Transport — hybrid push and pull
- Push ping: on workspace-to-live publish the source sends a small signed webhook to each subscribed target announcing what changed.
- Pull fetch: the target authenticates back to the source’s pull endpoint and downloads the full DAG snapshot.
- 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
- Bearer token per target (preshared, stored encrypted)
- Ed25519 signature over canonical JSON (RFC 8785) of the payload header. Keys are managed by the
KeyProviderInterfacefrommoselwal/content-provenance— file-based or Vault-backed, rotatable. - Replay protection via nonce plus timestamp; receivers cache nonces for 600 s and reject drift greater than ±300 s.
Scope — what is distributed out of the box
pageswith alltt_contentchildrensys_file_referenceplussys_file(binary fetched via signed URL, never inlined)sys_file_metadata,sys_category- Custom tables — registered per site via
settings.yaml - Optional: structured-content relations and annotations
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
| Command | Purpose |
|---|---|
cdsource:targets:list | List configured targets |
cdsource:targets:add | Register a target instance |
cdsource:targets:test | Send a probe ping to a target |
cdsource:outbox:process | Send all pending and retryable entries |
cdsource:outbox:retry | Re-enqueue failed entries |
cdsource:outbox:purge | Clean up old acked entries |
Backend modules
- Targets — CRUD for target sites
- Outbox — queue monitor, replay button, payload diff viewer
Architecture (DDD 4-Layer)
Strict DDD 4-layer architecture, enforced via deptrac:
| Layer | May depend on |
|---|---|
| Domain | Moselwal\ContentProvenance\* (interface only) |
| Application | Domain, ContentProvenance |
| Infrastructure | Application, Domain, Framework, ContentProvenance, StructuredContent |
| Presentation | Application, Domain, Framework |
License GPL-2.0-or-later (see repo). Codebase guidance: CLAUDE.md inside the package.
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.
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.