Messenger

Private member messaging, message requests, blocking, reporting and moderation.

Private, safety-aware member messaging for ProcessWire, with Message Requests, moderation, encrypted storage, and a ready-to-theme frontend application.

Messenger

Use Messenger when a ProcessWire site needs direct one-to-one conversations without handing trust policy, moderation, or private data to a third-party chat service. The module owns messaging state and safety controls; the site keeps ownership of profiles, matches, connections, page composition, and visual framework assets.

If this module saves you time, you can support it through GitHub Sponsors.

Account-bound call candidate


Messenger1.7.0 adds explicit authenticated account routing for call invitations, with legacy call registration/callback compatibility and fresh grant/device/ recipient checks. It also fixes historical MySQL grant/call collation comparisons. No site/provider/schema or native multi-account activation is implied. See verification and limits.

Account-bound notification candidate


Messenger1.6.9 adds explicit account_push registration so stored accounts may share a native message token without displacing each other. Messages and consented event reminders carry exact connection-routing metadata; legacy clients keep single-grant registration. No schema/provider/site activation or completed native multi-account/VoIP support is implied. See API.md.

Without-notification attachment candidate


Messenger1.6.4 adds explicit per-message suppression of email/message push, with an attachment-preview choice in the bundled web UI. Messages remain readable and unread counts work normally; recipient mute/preferences are not changed. Requires existing installed/enabled message tools; no new schema. Updated native clients must also honor the per-message flag. See API.md.

Native write acknowledgement candidate


Messenger 1.6.3 correlates native retries with the original accepted operation, including subsequent editing, hiding, deletion and expiry. Unavailable content is redacted instead of reappearing in client history. See API.md. No production deployment or schema change is implied.

Transient activity candidate


Messenger 1.6.2 adds a read-only, native-authorized recent direct-call journal from existing signaling rows. No schema/provider activation or audio/duration claim.

Messenger 1.6.1 adds encrypted, eight-second typing/voice-recording metadata for accepted direct/group conversations. Browser and Narzan clients provide local sharing controls, with invisible status, block and membership checks. It never sends a draft or audio as an activity indicator. The existing ProcessWire cache is used; no new schema or production deployment is implied. See API.md.

Conversation media catalog candidate


Messenger 1.6.0 adds a paginated catalog of an authorized conversation's photos, videos, documents, audio and HTTP(S) links. It searches message text and encrypted attachment filenames through bounded history scans, with the same member/join, hiding, expiry and moderation checks as the conversation. Browser and native clients can open the original message without replacing the unsent composer. See API.md; no schema or production deployment is implied.

Saved messages candidate


Messenger 1.5.9 adds an optional private Saved messages conversation per member. It is disabled by default, uses the existing encrypted site storage, and requires an explicit owner action. See API.md for the capability, ownership and legacy inbox boundary. This source update does not enable or deploy the feature on an existing website.

Features


  • Development candidate1.5.8 adds paginated conversation-history search in the API and web thread actions. It scans encrypted history in bounded pages without a plaintext index or the legacy global search's1,000-message cutoff; production acceptance remains separate.
  • One unique direct conversation per pair of ProcessWire users.
  • Configurable first contact: open, Message Requests, or a site-owned policy hook.
  • Request counts, accept/decline, pending-send limits, unread watermarks, archive, mute, and notification preferences.
  • Edit, delete-for-everyone, hide-for-self, block/unblock, and report actions with enforced ownership and time windows.
  • Explicit private contacts, per-chat mute, personal chat deletion, and server-enforced opt-in message expiry.
  • Member directories, expiring presence with invisible mode, authoritative read cursors and optional stored sent/read audit times.
  • Private encrypted file and voice attachments in accepted conversations (native API).
  • Optional explicit forwarding with independent private media copies, frozen selection revisions and atomic manual retries (1.5.5 development candidate; requires separate operator setup).
  • Optional encrypted reactions with counts/actual authors and exact desired-state retries (1.5.6 development candidate; requires the message-tools operator migration).
  • Optional personal chat pins and permission-scoped personal/shared message pins, with original-message navigation (1.5.7 development candidate; requires the explicit message-tools migration).
  • Cursor pagination, idempotent message creation, recipient search, and bounded encrypted-message search.
  • Per-member rate limits, temporary restrictions, immutable report evidence, and audited moderation decisions.
  • Separate permissions for moderation, evidence viewing, administration, export, and deletion boundaries.
  • Same-origin JSON API with ProcessWire sessions, CSRF validation, private headers, and no CORS opt-in.
  • Experimental opt-in native audio-call signaling with device ownership and private, consented call-quality reports; requires explicit operator schema and infrastructure setup.
  • Operator-installed ordinary-message push queue with encrypted standard APNs/FCM registrations, private generic alerts and dispatch-time membership/mute/read/session checks (1.5.2 development candidate, disabled by default).
  • Optional Narzan native authentication with browser consent, S256 PKCE, short-lived bearer tokens and per-device revocation; disabled by default.
  • XChaCha20-Poly1305 authenticated encryption at rest for messages and report content.
  • Selectable WireMail provider and preview-first local notification worker.
  • Responsive member UI plus an AdminThemeUikit dashboard, report queue, restrictions workspace, and settings navigation.
  • Presentation adapters for semantic styles, Designsystemet, UIkit, Bootstrap, Tailwind CSS, and custom role mappings.
  • Permission-gated administrative broadcasts to all eligible members or a selected role, with audience preview, encrypted source content, idempotent batch delivery, progress, cancellation, and audit history.

Requirements


  • ProcessWire 3.0.200 or newer
  • PHP 8.1 or newer
  • PHP sodium extension
  • An installation-specific $config->tableSalt, or preferably a dedicated $config->messengerEncryptionKey

Installation


  1. Copy Messenger to site/modules/.
  2. In ProcessWire, refresh modules and install Messenger.
  3. Grant messenger-moderate only to trusted moderators. Grant messenger-view-content separately to staff allowed to inspect preserved evidence.
  4. Review first-contact, rate-limit, frontend, email, and retention settings.
  5. Create the site's messages page/template using EXAMPLES.md.
  6. Hook Messenger::messagingDecision when the site's verified match or connection rules should decide first contact.

Fresh installation creates no sample conversations and grants no role permissions. Email delivery is disabled by default. Uninstall retains Messenger tables and permissions; private data is never silently purged.

Site integration


The consuming site owns the route, navigation, profile links, verified relationship facts, and shared-cache exclusions. Messenger supplies the application and enforces actor, participant, block, restriction, request, and rate policies:

<?php namespace ProcessWire;

if($modules->isInstalled('Messenger')) {
    /** @var Messenger $messenger */
    $messenger = $modules->get('Messenger');
    echo $messenger->renderApp($user);
}

Exclude the messages page and /messenger-api/ from shared caches. Messages are plain text and must never be rendered as trusted HTML.

For connection- or match-only messaging, return allow, request, or deny from the hookable policy after consulting the site's authoritative service:

$wire->addHookAfter('Messenger::messagingDecision', function(HookEvent $event) {
    [$actor, $recipient] = $event->arguments();
    if(!$event->wire()->matches->isVerifiedPair($actor, $recipient)) {
        $event->return = ['decision' => 'deny', 'reason' => 'Messaging requires a verified match.'];
    }
});

Frontend frameworks


The Frontend framework setting adds safe classes and data-*/ARIA attributes to stable Messenger UI roles. The site remains responsible for loading its selected framework stylesheet; Messenger never enqueues third-party framework assets. A custom JSON adapter can define or override role attributes:

{"input":{"class":"my-input"},"button_primary":{"class":"my-button","data-variant":"primary"},"badge":{"class":"my-badge"}}

Notifications


Messenger can follow the site-wide WireMail transport or use a specific installed WireMail module. Provider credentials remain in that provider's configuration and are not copied into Messenger.

Preview queued delivery before executing it from local cron:

php site/modules/Messenger/bin/messenger notifications --root=/path/to/site --dry-run
php site/modules/Messenger/bin/messenger notifications --root=/path/to/site --execute
php site/modules/Messenger/bin/messenger broadcasts --root=/path/to/site --dry-run
php site/modules/Messenger/bin/messenger broadcasts --root=/path/to/site --execute

Administrative broadcasts


Users with messenger-admin can open Setup → Messenger → Broadcasts, choose all eligible members or a selected role, write the private message, and check the exact eligible-recipient count. The reviewed audience and message must remain unchanged before the confirmation control and Send button become available. The first 100 recipients are processed immediately. Larger queues can be continued from the broadcast detail screen or by the explicitly enabled local CLI worker.

Each recipient receives one normal encrypted direct message from the administrator who created the broadcast. Recipient snapshots and deterministic delivery IDs make retries safe. Broadcasts bypass ordinary member first-contact, block, and sender-rate rules, but unavailable or restricted recipients are skipped at delivery time. Every lifecycle action is audited without copying message bodies into audit metadata.

Security and data lifecycle


Message bodies and report comments, evidence, and resolutions use versioned authenticated-encryption envelopes. The key is domain-separated from $config->messengerEncryptionKey, or from $config->tableSalt as a fallback, and is never stored in Messenger tables. Do not change that secret without a verified backup and an explicit key-rotation migration: existing ciphertext would become unreadable.

Optional WireWall integration

When the consuming site uses WireWall 1.13.0 or newer, Messenger settings can register /messenger-api/ and /messenger-mobile/ as an owner-scoped firewall exception. This is disabled by default. The option changes only WireWall's global traffic boundary: Messenger still enforces its own authentication, authorization, rate limits, CSRF policy, PKCE, callback allow-list and private response headers. Turning the option off removes only Messenger's registration; manual exceptions and registrations owned by other modules are preserved.

Message search decrypts and scans at most the newest 1,000 accessible messages because randomized ciphertext cannot be queried with SQL LIKE. Moderators do not gain conversation content from messenger-moderate; evidence access requires messenger-view-content.

Retention settings describe policy only. Permanent purge, anonymization, export, and key rotation remain explicit high-risk site operations.

Documentation


  • NARZAN.md — native protocol, web compatibility and activation gates.
  • API.md — supported PHP and REST interfaces
  • EXAMPLES.md — site integration examples
  • AGENTS.md — Olivia and coding-agent safety guidance
  • CHANGELOG.md — release history

License


MIT © 2026 Maxim Semenov.

Opt-in group development candidate


The1.5.3 source candidate adds group invitations, membership/roles, names/photos and compatible mobile/web management. It requires an explicit operator migration and activation; no live installation is implied. See group contract and remaining acceptance. Group links, polls, events, AI and group calls remain separate backlog stages.

Messenger1.6.5 adds an opt-in group-poll backend/API candidate: single-choice ballots, encrypted choices, aggregate results, exact-state vote retry and author/ administrator close. Explicit operator migration and enabled groups are required. Capability-gated web controls and Narzan integration use this contract; see API contract. No production install or completed store release is implied.

Messenger1.6.6 adds an optional group invitation-link candidate: authenticated preview/join, owner/admin creation and exact revocation, bounded lifetime/uses and current site-policy enforcement. Explicit operator migration and production acceptance remain required; this source update deploys nothing.

Directory role visibility — pending build14 integration


In Narzan mobile access, select Roles visible in the member directory and/or Roles hidden from the member directory. An empty include list preserves eligible discovery; excluded roles win when a person has several roles. Superusers are always omitted from general discovery. The same server-side directory policy applies to Narzan and the website. Existing conversations and explicit contacts remain available under their existing authorization; this setting does not grant or revoke messaging permissions. No schema change is needed. These source changes have not been installed on a consuming website.

Call reliability candidate 1.7.1


An opt-in relay pool, direct/STUN support, refresh recovery and ICE-restart signaling are prepared as a local candidate. Existing installations require the explicit operator setup in Call reliability; metadata upgrade alone does not alter schema or activate providers. Browser assets remain unchanged.

Client diagnostics — 1.7.2 candidate

Native metadata diagnostics require an explicit installClientDiagnostics($admin) installation. See API.md for privacy, quotas, encryption, private export and retention. No web assets or messaging tables are replaced by this feature. Not installed on consuming sites automatically.

More modules by Maxim Semenov

  • Context

    Export ProcessWire site context for AI development (JSON + TOON formats)
  • Mercato

    ProcessWire-native commerce toolkit: products, cart, checkout, orders, payments, discounts, fulfilment, inventory, recovery, reports, and demo storefront.
  • Ichiban (SEO control center)

    Comprehensive SEO module: meta/OG/schema, audit, redirects, revisions, email reports.
  • WireWall

    Advanced traffic firewall with VPN/Proxy/Tor detection, rate limiting, and JS challenge
  • Cookie

    Privacy & cookie consent management: banner, category-based async loading of scripts/embeds, consent log, Google Consent Mode v2, visual widget builder.
  • Ally (a11y)

    Self-hosted accessibility widget powered by Sienna (MIT). Adds font, contrast, language, and navigation tools to any page. No external CDN — the JS bundle is served from your own server.
  • Subscribe

    Newsletter subscription handler with lists, double opt-in, honeypot, rate limiting and unsubscribe link.
  • Squad

    AI integration for ProcessWire. Supports Anthropic, OpenAI, Google, xAI, and OpenRouter.
  • Dimensions

    Stores product dimensions (L×W×H) and weight with selectable units of measurement.

All modules by Maxim Semenov

Install and use modules at your own risk. Always have a site and database backup before installing new modules.