24 Commits
Author SHA1 Message Date
zeekay 8feb24ea1f One name for this fork, and it is ours
The server module named github.com/hanzoai/team/server/v8 — a path that
resolves to the retired workspace's repository, not this one — while
server/public still published github.com/mattermost/mattermost/server/public.
Both are github.com/hanzoteam/server/... now, which is where this code
actually lives.

That second half is what made the binary unbootable. Upstream's public path
stayed claimed by upstream, mattermost-plugin-ai imported it, and the build
linked public/model twice; public/plugin's gob.Register then ran twice under
one name and panicked at init, before main. Reverting the rename traded the
brand for a working binary. Rebranding the plugin alongside it needs no such
trade: the agents fork is github.com/hanzoteam/agents/v2 against our public
module, so no module named mattermost/mattermost is in the graph at all.

Measured: `go list -deps ./cmd/mattermost` names exactly one public/model, and
it is ours.
2026-08-28 23:35:36 -07:00
zeekay 8e84c8d5d6 The plugin API keeps the import path plugins import
Renaming server/public to github.com/hanzoai/team/server/public left the old
path unclaimed, and mattermost-plugin-ai still imports it — so the binary
linked public/model TWICE, ours and upstream's, and public/plugin's
gob.Register calls ran twice under one name:

  panic: gob: registering duplicate types for "[]*model.SlackAttachment":
         []*model.MessageAttachment != []*model.SlackAttachment

at init, before main. The server has not been able to start since that rename
landed, which is why the deployment is still answering from an older build.

server/v8 keeps its new name; nothing outside this repo imports it. public
does not, because its path is not a brand — it is the plugin API, and every
plugin written against Mattermost imports it by that name. Our own agents
fork is proof: it carries a replace pointing that exact path back here.

Reverting the public half is what makes the two copies one again. Measured
after: `go list -deps ./cmd/mattermost` names exactly one public/model, the
binary starts, and it serves.
2026-08-28 20:27:14 -07:00
zeekayandHanzo Dev 316dcf770f The module is ours, so its import path says so
Every package in this fork announced itself as github.com/mattermost/mattermost —
in 4,553 import lines, in both go.mod module declarations, and in the workspace.
A fork whose own import path names another company is one nobody can read as
theirs, and it is the first thing anyone sees at the top of every file.

server/v8 and server/public are now github.com/hanzoai/team/server/…, rewritten
mechanically and verified: `go build ./...` is clean for both modules and `go vet`
passes.

Three things are deliberately UNTOUCHED, because they are other people's names
rather than our branding: mattermost-plugin-ai and mattermost-plugin-mscalendar
are real dependencies we consume, github.com/mattermost/msgpack is a real
dependency, and the github.com/mattermost/mattermost/pull/… links in comments
point at real upstream discussions that renaming would turn into dead links.

server/public needs a `replace` to resolve locally now: the require still names a
version, and no proxy serves our path. The workspace alone does not satisfy a
require, which is exactly how this failed the first time.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-21 09:56:49 -07:00
Christopher PoileandGitHub 90abf16d30 [MM-69343] Add MessagesWillBeConsumedWithContext hook (#37091) 2026-06-17 21:21:46 +00:00
ce5644223a [MM-68400] Four plugin hooks and ChannelGuard enforcement (#36152)
* allow workflow_dispatch trigger for Server CI (for plugins CI)

* [MM-68402] MBE Phase 2: declare four generic plugin hooks (#36291)

* new hooks-only phase 2

* remove ChannelWillBeMoved

* remove RecapWillBeProcessed and MessageWillBeRewrittenByAI

Drop the AI/recap hooks from the new-hook surface; AI-LLM paths
remain uncovered in tech preview and are documented as residuals.

* [MM-68403] MBE Phase 3: ChannelGuards primitive (storage + cache + plugin API) (#36365)

* phase 3

* phase 3: register ChannelGuard mock in test setup helper

NewChannels' startup-time call to reloadGuardCache invokes
s.ChannelGuard().GetAll(); without an expectation on the mock store,
every test that sets up the server with GetMockStoreForSetupFunctions
panics during init.

* phase 3: register ChannelGuard mock in retrylayer test

retrylayer.New walks every store getter to wrap it; without the mock
expectation on ChannelGuard, TestRetry panics during layer construction.

* use rctx properly in the store methods

* phase 3: match rctx arg in testlib ChannelGuard mock

GetAll now takes request.CTX, so the testify expectation must include
mock.Anything; otherwise the call panics under the mocked store.

* phase 3: set api.ctx in TestChannelGuardLowercaseNormalization

The test constructs PluginAPI directly without a ctx, which used to
work when App.RegisterChannelGuard built its own EmptyContext. Now
that the App methods take rctx from the caller, the nil ctx panics
inside RequestContextWithMaster.

* [MM-68404] MBE Phase 4: App-layer plugin hook wiring (#36407)

* phase 4

* Fix nil rctx in TestChannelGuardLowercaseNormalization

The PluginAPI struct literal was missing ctx: rctx after a refactor
moved the rctx declaration below the struct construction, leaving
api.ctx as nil. This caused a nil pointer dereference in reloadGuardCache
when RegisterChannelGuard called store.RequestContextWithMaster(nil).

* Remove ChannelWillBeMoved hook call from MoveChannel (phase 4)

The hook and its ID were removed from mbe-phase-2 but the call site in
MoveChannel and its i18n string were not cleaned up during the rebase.

* remove channel will be moved test

* Remove RecapWillBeProcessed and MessageWillBeRewrittenByAI hook calls (phase 4)

The hooks and their IDs were removed from mbe-phase-2 but the call sites
in ProcessRecapChannel and RewriteMessage, their i18n strings, and their
tests were not cleaned up during the rebase.

* Revert channel_id plumbing on rewrite endpoint (phase 4)

The channel_id field on RewriteRequest was added in phase 4 to feed the
synthetic post passed to MessageWillBeRewrittenByAI. With that hook
removed from mbe-phase-2, channel_id has no consumer; revert the field,
the api4 validation, the app.RewriteMessage parameter, and the
corresponding webapp client + hook plumbing.

* [MM-68555] MBE Phase 5: Channel-guard enforcement + two-phase dispatch (#36473)

* phase 5

* Bake plugin counter-file paths into source instead of env vars

t.Setenv panics when an ancestor test calls t.Parallel, so the two
channel-guard tests broke under ENABLE_FULLY_PARALLEL_TESTS in CI.
Build each plugin source per-subtest with its temp file path embedded
as a Go literal — same pattern as TestPluginUploadsAPI.

* Remove guarded helpers and tests for dropped hooks (phase 5)

The runGuardedRecapWillBeProcessed and runGuardedMessageWillBeRewrittenByAI
helpers were never wired (their app-layer call sites were already removed
in the phase-4 cleanup), and the corresponding sub-tests across panic /
allow / reject / partial plugins reference hooks that no longer exist.

* [MM-68405] MBE Phase 6: fire MessagesWillBeConsumed on the edit path (#36475)

---------

---------

---------

---------

* rebase onto master

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-05-21 18:16:05 +00:00
a721d9c120 [MM-68655] Surface RPC errors from plugin hooks (#36414)
* add WithRPCErr hooks (server-facing/internal only)

* zero _returns on RPC failure in WithRPCErr companions

Aligns the WithRPCErr template with the HooksRPCErr godoc contract: when
g.client.Call returns a transport error, gob may have partially decoded the
reply. Reassign _returns to a zero value before destructuring so callers always
receive zeroed outputs alongside a non-nil transport error.

* rename HooksRPCErr to HooksWithRPCErr for naming consistency

Every related symbol uses the WithRPCErr suffix (MessageHasBeenPostedWithRPCErr,
RunMultiPluginHookWithRPCErr, RunMultiHookWithRPCErr, etc.). Aligning the
interface name removes the only outlier and makes the convention uniform.

* rename rpcErrImpl to hooksWithRPCErrImpl

Mirrors the existing hooksImpl/Hooks naming pattern on hooksTimerLayer.

* add supervisor.HooksWithRPCErr() and drop runtime type assertion

The old path did rp.supervisor.Hooks().(HooksWithRPCErr) and handled the
"doesn't implement" branch — but that branch was structurally unreachable
(the compile-time `_ HooksWithRPCErr = (*hooksTimerLayer)(nil)` assertion
guards it).

Change supervisor.hooks from `Hooks` to the concrete `*hooksTimerLayer`
(which implements both interfaces, enforced at field assignment), add a
parallel HooksWithRPCErr() accessor, and call it directly. Hooks() keeps
its public Hooks-interface signature via implicit conversion at return.

* drop "implemented by" clause from HooksWithRPCErr godoc

Both hooksRPCClient and hooksTimerLayer satisfy the interface, and naming
implementations in interface godocs adds rot — the contract is what readers
need, not the list of wrappers.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-05-05 10:41:11 -04:00
Doug LauderandGitHub 5bc792c4b5 MM-68016, MM-68017, MM-68018 Add plugin pre-hooks for membership and channel archive (#35731)
* MM-68016, MM-68017, MM-68018 Add plugin pre-hooks for channel member add, team member add, and channel archive

  Enable plugins to intercept and reject (or modify) three operations before
  they are persisted: adding a channel member, adding a team member, and
  archiving a channel. These are the three high-priority hooks from epic
  MM-68003.
2026-03-25 08:45:17 -04:00
8edeae700d feat: pluginapi: filewillbedownloaded / sendtoastmessage (#34596)
* feat: filewillbedonwloaded hook

* feat: error popup

* chore: make generated pluginapi

* tests

* feat: different errors for different download types

* feat: allow toast positions

* fix: avoid using deprecated i18n function

* feat: add plugin API to show toasts

* feat: downloadType parameter

* tests: updated tests

* chore: make check-style

* chore: i18n

* chore: missing fields in tests

* chore: sorted i18n for webapp

* chore: run mmjstool

* test: fixed webapp tests with new changes

* test: missing mocks

* fix: ensure one-file attachments (previews) are handler properly as thumbnails

* chore: lint

* test: added new logic to tests

* chore: lint

* Add SendToastMessage API and FileWillBeDownloaded hook

- Introduced SendToastMessage method for sending toast notifications to users with customizable options.
- Added FileWillBeDownloaded hook to handle file download requests, allowing plugins to control access to files.
- Updated related types and constants for file download handling.
- Enhanced PluginSettings to include HookTimeoutSeconds for better timeout management.

* Update webapp/channels/src/components/single_image_view/single_image_view.tsx

* chore: copilot reviews

* test: head requests

* chore: linted the webapp

* tests: fixed path

* test: fixed mocked args

* allow sending message to a connection directly

* fix: hook thread safety

* chore: formatting

* chore: remove configuration from system console

* chore: release version

* chore: update signature

* chore: update release version

* chore: addressed comments

* fix: update file rejection handling to use 403 Forbidden status and include rejection reason header

* Fix nil pointer panic in runFileWillBeDownloadedHook

The atomic.Value in runFileWillBeDownloadedHook can be nil if no
plugins implement the FileWillBeDownloaded hook. This causes a panic
when trying to assert the nil interface to string.

This fix adds a nil check before the type assertion, defaulting to
an empty string (which allows the download) when no hooks have run.

Fixes:
- TestUploadDataMultipart/success panic
- TestUploadDataMultipart/resume_success panic

* test: move the logout test last

* chore: restored accidential deletion

* chore: lint

* chore: make generated

* refactor: move websocket events to new package

* chore: go vet

* chore: missing mock

* chore: revert incorrect fmt

* chore: import ordering

* chore: npm i18n-extract

* chore: update constants.tsx from master

* chore: make i18n-extract

* revert: conflict merge

* fix: add missing isFileRejected prop to SingleImageView tests

* fix: mock fetch in SingleImageView tests for async thumbnail check

The component now performs an async fetch to check thumbnail availability
before rendering. Tests need to mock fetch and use waitFor to handle
the async state updates.

* refactor: move hook logic to app layer

* chore: update version to 11.5

* Scope file download rejection toast to the requesting connection

Thread the Connection-Id header through RunFileWillBeDownloadedHook and
sendFileDownloadRejectedEvent so the WebSocket event is sent only to the
connection that initiated the download, instead of all connections for
the user.

---------

Co-authored-by: Hanzo Dev <[email protected]>
2026-02-16 17:10:39 +01:00
David KrauserandGitHub 069aad467d [MM-64840] Add EmailNotificationWillBeSent Plugin Hook (#33421) 2025-08-05 09:09:07 -04:00
Ben CookeandGitHub debbac82cb Plugin groups (#30320)
* add new pluginapi methods

* SAML login hook

* set ReAddRemovedMembers to true for plugin groups

* change to DoLogin signature for SAML
2025-03-13 12:00:15 -04:00
617f7b3cb2 Make support packet composable with plugins (#26403)
---------

Co-authored-by: Ben Schumacher <[email protected]>
2024-04-12 10:05:58 +02:00
bfaae6ea9b Plugin API hook for Shared Channel file attachment sync (#25874)
* option for auto inviting plugin to all shared channels.

* auto-invite remotes to shared channels when flag set

* fix unit test

* immediately ping new remotes; fix unique siteurl bug

* make i18n-extract

* fix translations

* plugin hooks for file attachments

* hook for profile image sync

* fix profile image sync

* fix unit test

---------

Co-authored-by: Mattermost Build <[email protected]>
2024-01-16 15:48:51 +01:00
Harrison HealeyandGitHub 0d76a3fcdb MM-56082 Add PreferencesHaveChanged plugin hook (#25659)
* Add interface for PreferencesHaveChanged hook

* Add context to preference-related methods of App

* Implement PreferencesHaveChanged

* Re-add missing "fmt" import

* Update minimum server version for the new hook

* Remove pointers to be consistent with other preference APIs
2024-01-03 12:25:53 -05:00
Doug LauderandGitHub a69d75e540 Shared channels plugin APIs for MS Teams plugin (#25805)
New plugin APIs and hooks for accessing Shared Channels service via plugin. 

- RegisterPluginForSharedChannels(opts model.RegisterPluginOpts) (remoteID string, err error)
- UnregisterPluginForSharedChannels(pluginID string) error
- ShareChannel(sc *model.SharedChannel) (*model.SharedChannel, error)
- UpdateSharedChannel(sc *model.SharedChannel) (*model.SharedChannel, error)
- UnshareChannel(channelID string) (unshared bool, err error)
- UpdateSharedChannelCursor(channelID, remoteID string, cusror model.GetPostsSinceForSyncCursor) error
- SyncSharedChannel(channelID string) error
- InviteRemoteToChannel(channelID string, remoteID string, userID string) error
- UninviteRemoteFromChannel(channelID string, remoteID string) error

Hooks
- OnSharedChannelsSyncMsg(msg *model.SyncMsg, rc *model.RemoteCluster) (model.SyncResponse, error)
- OnSharedChannelsPing(rc *model.RemoteCluster) bool
2023-12-22 17:00:27 -05:00
c13fd1abb6 [MM-55268] Implement ServeMetrics plugins hook (#24249)
* Implement ServeMetrics plugins hook

* Update error id

* Simplify

* Revert "Simplify"

This reverts commit c9dc5d5eac6c933ff69e158cf3e34d0973bd3bcd.

* Add comment and error handler

* Wrap error

* Update translation file

---------

Co-authored-by: Mattermost Build <[email protected]>
2023-11-17 14:39:06 -06:00
29f9e8409c (feature) New MessagesWillBeConsumed Server Plugin Hook (#23305)
* feature: implemented basic MessageWillBeConsumed hook and applied on GetSinglePost method.

* use hook in get methods

* chore: refactored hook usage and created utils functions to apply hook

* bugfix: single post not updating

* chore: adjusted hook to return post

* chore: reverted some uneeded  changes

* chore: updated hook to accept slice of posts

* bugfix: slice filled with niil values

* chore: MessageWillBeConsumed ranamed to MessagesWillBeConsumed

* Update plugin/hooks.go

Co-authored-by: Jesse Hallam <[email protected]>

* Add feature flag

* Update min version

* update tests to account for feature flag

* fix linting issues

---------

Co-authored-by: Matej Topolovac <>
Co-authored-by: mtopolovac <[email protected]>
Co-authored-by: Jesse Hallam <[email protected]>
Co-authored-by: Kevin Hsieh <[email protected]>
Co-authored-by: Jesse Hallam <[email protected]>
2023-10-23 11:12:46 -03:00
0a855b5b21 Adding 'MessageHasBeenDeleted' hook to plugins (#22476)
* Adding 'MessageHasBeenDeleted' hook to plugins

* Remove debug logs

* Add unit test

* Bumping the required version

* Fix CI problems

* Increasing the minimum version

* go fmt

---------

Co-authored-by: Ben Schumacher <[email protected]>
Co-authored-by: Mattermost Build <[email protected]>
2023-09-14 18:33:22 +02:00
5f910f7f9c Add UserHasBeenDeactivated plugin hook (#20894)
Co-authored-by: Ben Schumacher <[email protected]>
2023-08-30 08:55:20 +02:00
06d6969ae8 MM-53924 - Implement push notifications plugin hook and plugin api method (#24350)
* Revert "MM-52804 - Implement SendPushNotification plugin api method (#24273)"

This reverts commit 4f5fb6bcd0.

* Revert "MM-53924 - Implement NotificationWillBePushed plugin hook (#24263)"

This reverts commit 0f1f37efbe.

* implement NotificationWillBePushed plugin hook

* implement SendPushNotification plugin api method

* move where we're setting post and channel type

* fix comment

---------

Co-authored-by: Mattermost Build <[email protected]>
2023-08-24 12:33:53 -04:00
Christopher PoileandGitHub 0f1f37efbe MM-53924 - Implement NotificationWillBePushed plugin hook (#24263)
* add NotificationWillBePushed hook

* mocks

* use a struct for hook parameters; simplify number of parameters sent across RPC

* missing wg.Wait

* change to a bool return value
2023-08-18 12:01:50 -04:00
Jesse HallamandGitHub 6d49232880 MM-53358: Revert Threads Everywhere (#23882)
Remove changes related to the unshipped threads everywhere feature, including commits c8bd2a6af6 and 372e34132c.

Since a version of Playbooks shipped calling this experimental API, keep a `nil` implementation to avoid breaking compatibility. We remove the hooks altogether, but keep the numbering again to avoid breaking compatbility.

Fixes: https://mattermost.atlassian.net/browse/MM-53358
2023-06-30 15:31:25 -03:00
Claudio CostaandGitHub 0a6ccb7ab1 [MM-52924] Implement ConfigurationWillBeSaved plugin hook (#23567)
* Implement ConfigurationWillBeSaved plugin hook

* Add comment

* Update comment

* Fix potential nil dereference if plugin environment is unset

* Address PR review
2023-06-12 18:23:02 -06:00
Agniva De SarkerandGitHub c1500d628c MM-53032: Fix module path after repo rename (#23689)
It was a good decision in hindsight to keep the public module as 0.x
because this would have been a breaking change again.

https://mattermost.atlassian.net/browse/MM-53032
```release-note
Changed the Go module path from github.com/mattermost/mattermost-server/server/v8 to github.com/mattermost/mattermost/server/v8.

For the public facing module, it's path is also changed from github.com/mattermost/mattermost-server/server/public to github.com/mattermost/mattermost/server/public
```
2023-06-11 10:54:35 +05:30
Jesse HallamandGitHub f9bd59e068 Expose public/ API as submodule (#23345)
* model -> public/model

* plugin -> public/plugin

* public/model/utils -> public/utils

* platform/shared/mlog -> public/shared/mlog

* platform/shared/i18n -> public/shared/i18n

* platform/shared/markdown -> public/shared/markdown

* platform/services/timezones -> public/shared/timezones

* channels/einterfaces -> einterfaces

* expose public/ submodule

* go mod tidy

* .github: cache-dependency-path, setup-go-work

* modules-tidy for public/ too

* remove old gomodtidy
2023-05-10 13:07:02 -03:00