Ports the gooyal notifications client (as already used by advertising)
and wires it into the previously-empty PushPublisher: on each message
send, the other conversation participant(s) get a push notification
with the sender's name and a message preview. Failures are swallowed
per-recipient so a down notifications service degrades silently rather
than breaking message sending.
Requires NOTIFICATIONS_BASE_PUBLIC_URL and the
notifications.application.push:send OAuth2 scope to be configured
before it will actually deliver.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Conversations can now be given an optional title at creation
(POST /api/chats/), stored locally on the Conversation model and
returned in create/list/close/reopen responses.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Renames PK/reference fields across chat models, services, serializers,
views, urls, websocket routing, and events (id->uuid, user_id->user_uuid,
chat_id->chat_uuid, sender_id->sender_uuid, user_1_id/user_2_id->
user_1_uuid/user_2_uuid) for consistency with the uuid-named PK
convention already used in core/users/gooyal_oauth2. Mattermost's own
opaque identifiers (post_id, channel_id, mattermost_user_id) are left
unchanged since they are not UUIDs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Frontend now uploads media directly to MinIO and sends only the
resulting object_key; the backend never touches file bytes. Mattermost
post bodies carry "<type>:<object_key>" instead of a permanent public
URL, and download links are signed fresh on every read (send + list)
so they can't outlive their expiry. Also wires up MINIO_SECURE, which
settings.py previously never read from env.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>